summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp38
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp14
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp20
-rw-r--r--clang/lib/CodeGen/CGObjC.cpp10
-rw-r--r--clang/lib/CodeGen/CGObjCGNU.cpp8
-rw-r--r--clang/lib/CodeGen/CGObjCMac.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h10
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h12
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.
OpenPOWER on IntegriCloud