diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 38 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprComplex.cpp | 20 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCGNU.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 12 |
8 files changed, 73 insertions, 41 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 5dea876451f..70cb4713e69 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1391,8 +1391,19 @@ llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) { return GetFunctionType(*Info); } +static void AddAttributesFromFunctionProtoType(ASTContext &Ctx, + llvm::AttrBuilder &FuncAttrs, + const FunctionProtoType *FPT) { + if (!FPT) + return; + + if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) && + FPT->isNothrow(Ctx)) + FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); +} + void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, - const Decl *TargetDecl, + CGCalleeInfo CalleeInfo, AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite) { @@ -1405,6 +1416,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, if (FI.isNoReturn()) FuncAttrs.addAttribute(llvm::Attribute::NoReturn); + // If we have information about the function prototype, we can learn + // attributes form there. + AddAttributesFromFunctionProtoType(getContext(), FuncAttrs, + CalleeInfo.getCalleeFunctionProtoType()); + + const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); + // FIXME: handle sseregparm someday... if (TargetDecl) { if (TargetDecl->hasAttr<ReturnsTwiceAttr>()) @@ -1417,10 +1435,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { - const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>(); - if (FPT && !isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) && - FPT->isNothrow(getContext())) - FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + AddAttributesFromFunctionProtoType( + getContext(), FuncAttrs, Fn->getType()->getAs<FunctionProtoType>()); // Don't use [[noreturn]] or _Noreturn for a call to a virtual function. // These attributes are not inherited by overloads. const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn); @@ -3077,7 +3093,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *Callee, ReturnValueSlot ReturnValue, const CallArgList &CallArgs, - const Decl *TargetDecl, + CGCalleeInfo CalleeInfo, llvm::Instruction **callOrInvoke) { // FIXME: We no longer need the types from CallArgs; lift up and simplify. @@ -3406,8 +3422,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, unsigned CallingConv; CodeGen::AttributeListType AttributeList; - CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList, - CallingConv, true); + CGM.ConstructAttributeList(CallInfo, CalleeInfo, AttributeList, CallingConv, + true); llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(), AttributeList); @@ -3487,9 +3503,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // lexical order, so deactivate it and run it manually here. CallArgs.freeArgumentMemory(*this); - if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) + if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) { + const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>()) Call->setTailCallKind(llvm::CallInst::TCK_NoTail); + } RValue Ret = [&] { switch (RetAI.getKind()) { @@ -3562,6 +3580,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm_unreachable("Unhandled ABIArgInfo::Kind"); } (); + const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); + if (Ret.isScalar() && TargetDecl) { if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) { llvm::Value *OffsetValue = nullptr; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index a3f863fc0af..c2db7287d61 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3741,12 +3741,21 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) { RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, const CallExpr *E, ReturnValueSlot ReturnValue, - const Decl *TargetDecl, llvm::Value *Chain) { + CGCalleeInfo CalleeInfo, llvm::Value *Chain) { // Get the actual function type. The callee type will always be a pointer to // function type or a block pointer type. assert(CalleeType->isFunctionPointerType() && "Call must have function pointer type!"); + // Preserve the non-canonical function type because things like exception + // specifications disappear in the canonical type. That information is useful + // to drive the generation of more accurate code for this call later on. + const FunctionProtoType *NonCanonicalFTP = CalleeType->getAs<PointerType>() + ->getPointeeType() + ->getAs<FunctionProtoType>(); + + const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); + if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) // We can only guarantee that a function is called from the correct // context/function based on the appropriate target attributes, @@ -3867,7 +3876,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, Callee = Builder.CreateBitCast(Callee, CalleeTy, "callee.knr.cast"); } - return EmitCall(FnInfo, Callee, ReturnValue, Args, TargetDecl); + return EmitCall(FnInfo, Callee, ReturnValue, Args, + CGCalleeInfo(NonCanonicalFTP, TargetDecl)); } LValue CodeGenFunction:: diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 4b45bce098a..ccdb53287e9 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -585,19 +585,25 @@ ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName, // We *must* use the full CG function call building logic here because the // complex type has special ABI handling. We also should not forget about // special calling convention which may be used for compiler builtins. - const CGFunctionInfo &FuncInfo = - CGF.CGM.getTypes().arrangeFreeFunctionCall( - Op.Ty, Args, FunctionType::ExtInfo(/* No CC here - will be added later */), - RequiredArgs::All); + + // We create a function qualified type to state that this call does not have + // any exceptions. + FunctionProtoType::ExtProtoInfo EPI; + EPI = EPI.withExceptionSpec( + FunctionProtoType::ExceptionSpecInfo(EST_BasicNoexcept)); + SmallVector<QualType, 4> ArgsQTys( + 4, Op.Ty->castAs<ComplexType>()->getElementType()); + QualType FQTy = CGF.getContext().getFunctionType(Op.Ty, ArgsQTys, EPI); + const CGFunctionInfo &FuncInfo = CGF.CGM.getTypes().arrangeFreeFunctionCall( + Args, cast<FunctionType>(FQTy.getTypePtr()), false); + llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(FuncInfo); llvm::Constant *Func = CGF.CGM.CreateBuiltinFunction(FTy, LibCallName); llvm::Instruction *Call; RValue Res = CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args, - nullptr, &Call); + FQTy->getAs<FunctionProtoType>(), &Call); cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getBuiltinCC()); - cast<llvm::CallInst>(Call)->setDoesNotThrow(); - return Res.getComplexVal(); } diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 766102e723e..6865f974fc2 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -949,11 +949,11 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, // FIXME: We shouldn't need to get the function info here, the // runtime already should have computed it to build the function. llvm::Instruction *CallInstruction; - RValue RV = EmitCall(getTypes().arrangeFreeFunctionCall(propType, args, - FunctionType::ExtInfo(), - RequiredArgs::All), - getPropertyFn, ReturnValueSlot(), args, nullptr, - &CallInstruction); + RValue RV = EmitCall( + getTypes().arrangeFreeFunctionCall( + propType, args, FunctionType::ExtInfo(), RequiredArgs::All), + getPropertyFn, ReturnValueSlot(), args, CGCalleeInfo(), + &CallInstruction); if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(CallInstruction)) call->setTailCall(); diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 1e5db240429..f0af3e924c0 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -1327,8 +1327,8 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD); llvm::Instruction *call; - RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, nullptr, - &call); + RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, + CGCalleeInfo(), &call); call->setMetadata(msgSendMDKind, node); return msgRet; } @@ -1440,8 +1440,8 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, imp = EnforceType(Builder, imp, MSI.MessengerType); llvm::Instruction *call; - RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, nullptr, - &call); + RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, + CGCalleeInfo(), &call); call->setMetadata(msgSendMDKind, node); diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index dad172b5651..78f32363a43 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -1947,7 +1947,7 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, llvm::Instruction *CallSite; Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType); RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs, - nullptr, &CallSite); + CGCalleeInfo(), &CallSite); // Mark the call as noreturn if the method is marked noreturn and the // receiver cannot be null. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index d0f37e6fa45..176c0909cea 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2624,16 +2624,14 @@ public: /// /// \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, - ReturnValueSlot ReturnValue, - const CallArgList &Args, - const Decl *TargetDecl = nullptr, + RValue EmitCall(const CGFunctionInfo &FnInfo, llvm::Value *Callee, + ReturnValueSlot ReturnValue, const CallArgList &Args, + CGCalleeInfo CalleeInfo = CGCalleeInfo(), llvm::Instruction **callOrInvoke = nullptr); RValue EmitCall(QualType FnType, llvm::Value *Callee, const CallExpr *E, ReturnValueSlot ReturnValue, - const Decl *TargetDecl = nullptr, + CGCalleeInfo CalleeInfo = CGCalleeInfo(), llvm::Value *Chain = nullptr); RValue EmitCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue = ReturnValueSlot()); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index b9a5c8d2e6a..e435a7721d9 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -968,16 +968,14 @@ public: /// function type. /// /// \param Info - The function type information. - /// \param TargetDecl - The decl these attributes are being constructed - /// for. If supplied the attributes applied to this decl may contribute to the - /// function attributes and calling convention. + /// \param CalleeInfo - The callee information these attributes are being + /// constructed for. If valid, the attributes applied to this decl may + /// contribute to the function attributes and calling convention. /// \param PAL [out] - On return, the attribute list to use. /// \param CallingConv [out] - On return, the LLVM calling convention to use. void ConstructAttributeList(const CGFunctionInfo &Info, - const Decl *TargetDecl, - AttributeListType &PAL, - unsigned &CallingConv, - bool AttrOnCallSite); + CGCalleeInfo CalleeInfo, AttributeListType &PAL, + unsigned &CallingConv, bool AttrOnCallSite); // Fills in the supplied string map with the set of target features for the // passed in function. |