r224167 - Implement the __builtin_call_with_static_chain GNU extension.
Peter Collingbourne
peter at pcc.me.uk
Fri Dec 12 15:41:26 PST 2014
Author: pcc
Date: Fri Dec 12 17:41:25 2014
New Revision: 224167
URL: http://llvm.org/viewvc/llvm-project?rev=224167&view=rev
Log:
Implement the __builtin_call_with_static_chain GNU extension.
The extension has the following syntax:
__builtin_call_with_static_chain(Call, Chain)
where Call must be a function call expression and Chain must be of pointer type
This extension performs a function call Call with a static chain pointer
Chain passed to the callee in a designated register. This is useful for
calling foreign language functions whose ABI uses static chain pointers
(e.g. to implement closures).
Differential Revision: http://reviews.llvm.org/D6332
Added:
cfe/trunk/test/CodeGenCXX/call-with-static-chain.cpp
cfe/trunk/test/Sema/call-with-static-chain.c
cfe/trunk/test/SemaCXX/call-with-static-chain.cpp
Modified:
cfe/trunk/include/clang/Basic/Builtins.def
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h
cfe/trunk/lib/CodeGen/CGBuiltin.cpp
cfe/trunk/lib/CodeGen/CGCall.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/CodeGen/CodeGenTypes.h
cfe/trunk/lib/CodeGen/TargetInfo.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
Modified: cfe/trunk/include/clang/Basic/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Builtins.def (original)
+++ cfe/trunk/include/clang/Basic/Builtins.def Fri Dec 12 17:41:25 2014
@@ -497,6 +497,7 @@ BUILTIN(__builtin_unreachable, "v", "nr"
BUILTIN(__builtin_shufflevector, "v." , "nc")
BUILTIN(__builtin_convertvector, "v." , "nct")
BUILTIN(__builtin_alloca, "v*z" , "n")
+BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
// "Overloaded" Atomic operator builtins. These are overloaded to support data
// types of i8, i16, i32, i64, and i128. The front-end sees calls to the
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Dec 12 17:41:25 2014
@@ -6917,6 +6917,17 @@ def err_convertvector_non_vector_type :
def err_convertvector_incompatible_vector : Error<
"first two arguments to __builtin_convertvector must have the same number of elements">;
+def err_first_argument_to_cwsc_not_call : Error<
+ "first argument to __builtin_call_with_static_chain must be a non-member call expression">;
+def err_first_argument_to_cwsc_block_call : Error<
+ "first argument to __builtin_call_with_static_chain must not be a block call">;
+def err_first_argument_to_cwsc_builtin_call : Error<
+ "first argument to __builtin_call_with_static_chain must not be a builtin call">;
+def err_first_argument_to_cwsc_pdtor_call : Error<
+ "first argument to __builtin_call_with_static_chain must not be a pseudo-destructor call">;
+def err_second_argument_to_cwsc_not_pointer : Error<
+ "second argument to __builtin_call_with_static_chain must be of pointer type">;
+
def err_vector_incorrect_num_initializers : Error<
"%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">;
def err_altivec_empty_initializer : Error<"expected initializer">;
Modified: cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h (original)
+++ cfe/trunk/include/clang/CodeGen/CGFunctionInfo.h Fri Dec 12 17:41:25 2014
@@ -352,6 +352,9 @@ class CGFunctionInfo : public llvm::Fold
/// Whether this is an instance method.
unsigned InstanceMethod : 1;
+ /// Whether this is a chain call.
+ unsigned ChainCall : 1;
+
/// Whether this function is noreturn.
unsigned NoReturn : 1;
@@ -360,7 +363,7 @@ class CGFunctionInfo : public llvm::Fold
/// How many arguments to pass inreg.
unsigned HasRegParm : 1;
- unsigned RegParm : 4;
+ unsigned RegParm : 3;
RequiredArgs Required;
@@ -380,7 +383,8 @@ class CGFunctionInfo : public llvm::Fold
public:
static CGFunctionInfo *create(unsigned llvmCC,
- bool InstanceMethod,
+ bool instanceMethod,
+ bool chainCall,
const FunctionType::ExtInfo &extInfo,
CanQualType resultType,
ArrayRef<CanQualType> argTypes,
@@ -412,6 +416,8 @@ public:
bool isInstanceMethod() const { return InstanceMethod; }
+ bool isChainCall() const { return ChainCall; }
+
bool isNoReturn() const { return NoReturn; }
/// In ARC, whether this function retains its return value. This
@@ -462,6 +468,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) {
ID.AddInteger(getASTCallingConvention());
ID.AddBoolean(InstanceMethod);
+ ID.AddBoolean(ChainCall);
ID.AddBoolean(NoReturn);
ID.AddBoolean(ReturnsRetained);
ID.AddBoolean(HasRegParm);
@@ -473,12 +480,14 @@ public:
}
static void Profile(llvm::FoldingSetNodeID &ID,
bool InstanceMethod,
+ bool ChainCall,
const FunctionType::ExtInfo &info,
RequiredArgs required,
CanQualType resultType,
ArrayRef<CanQualType> argTypes) {
ID.AddInteger(info.getCC());
ID.AddBoolean(InstanceMethod);
+ ID.AddBoolean(ChainCall);
ID.AddBoolean(info.getNoReturn());
ID.AddBoolean(info.getProducesResult());
ID.AddBoolean(info.getHasRegParm());
Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Fri Dec 12 17:41:25 2014
@@ -185,7 +185,8 @@ static llvm::Value *EmitOverflowIntrinsi
}
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
- unsigned BuiltinID, const CallExpr *E) {
+ unsigned BuiltinID, const CallExpr *E,
+ ReturnValueSlot ReturnValue) {
// See if we can constant fold this builtin. If so, don't emit it at all.
Expr::EvalResult Result;
if (E->EvaluateAsRValue(Result, CGM.getContext()) &&
@@ -1566,6 +1567,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(
case Builtin::BI__noop:
// __noop always evaluates to an integer literal zero.
return RValue::get(ConstantInt::get(IntTy, 0));
+ case Builtin::BI__builtin_call_with_static_chain: {
+ const CallExpr *Call = cast<CallExpr>(E->getArg(0));
+ const Expr *Chain = E->getArg(1);
+ return EmitCall(Call->getCallee()->getType(),
+ EmitScalarExpr(Call->getCallee()), Call, ReturnValue,
+ Call->getCalleeDecl(), EmitScalarExpr(Chain));
+ }
case Builtin::BI_InterlockedExchange:
case Builtin::BI_InterlockedExchangePointer:
return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E);
Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Fri Dec 12 17:41:25 2014
@@ -83,14 +83,15 @@ CodeGenTypes::arrangeFreeFunctionType(Ca
// When translating an unprototyped function type, always use a
// variadic type.
return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(),
- false, None, FTNP->getExtInfo(),
- RequiredArgs(0));
+ /*instanceMethod=*/false,
+ /*chainCall=*/false, None,
+ FTNP->getExtInfo(), RequiredArgs(0));
}
/// Arrange the LLVM function layout for a value of the given function
/// type, on top of any implicit parameters already stored.
static const CGFunctionInfo &
-arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool IsInstanceMethod,
+arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod,
SmallVectorImpl<CanQualType> &prefix,
CanQual<FunctionProtoType> FTP) {
RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size());
@@ -98,7 +99,8 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CG
for (unsigned i = 0, e = FTP->getNumParams(); i != e; ++i)
prefix.push_back(FTP->getParamType(i));
CanQualType resultType = FTP->getReturnType().getUnqualifiedType();
- return CGT.arrangeLLVMFunctionInfo(resultType, IsInstanceMethod, prefix,
+ return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod,
+ /*chainCall=*/false, prefix,
FTP->getExtInfo(), required);
}
@@ -107,7 +109,8 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CG
const CGFunctionInfo &
CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) {
SmallVector<CanQualType, 16> argTypes;
- return ::arrangeLLVMFunctionInfo(*this, false, argTypes, FTP);
+ return ::arrangeLLVMFunctionInfo(*this, /*instanceMethod=*/false, argTypes,
+ FTP);
}
static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
@@ -219,7 +222,9 @@ CodeGenTypes::arrangeCXXStructorDeclarat
: TheCXXABI.hasMostDerivedReturn(GD)
? CGM.getContext().VoidPtrTy
: Context.VoidTy;
- return arrangeLLVMFunctionInfo(resultType, true, argTypes, extInfo, required);
+ return arrangeLLVMFunctionInfo(resultType, /*instanceMethod=*/true,
+ /*chainCall=*/false, argTypes, extInfo,
+ required);
}
/// Arrange a call to a C++ method, passing the given arguments.
@@ -243,7 +248,9 @@ CodeGenTypes::arrangeCXXConstructorCall(
: Context.VoidTy;
FunctionType::ExtInfo Info = FPT->getExtInfo();
- return arrangeLLVMFunctionInfo(ResultType, true, ArgTypes, Info, Required);
+ return arrangeLLVMFunctionInfo(ResultType, /*instanceMethod=*/true,
+ /*chainCall=*/false, ArgTypes, Info,
+ Required);
}
/// Arrange the argument and result information for the declaration or
@@ -262,8 +269,9 @@ CodeGenTypes::arrangeFunctionDeclaration
// non-variadic type.
if (isa<FunctionNoProtoType>(FTy)) {
CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>();
- return arrangeLLVMFunctionInfo(noProto->getReturnType(), false, None,
- noProto->getExtInfo(), RequiredArgs::All);
+ return arrangeLLVMFunctionInfo(
+ noProto->getReturnType(), /*instanceMethod=*/false,
+ /*chainCall=*/false, None, noProto->getExtInfo(), RequiredArgs::All);
}
assert(isa<FunctionProtoType>(FTy));
@@ -307,8 +315,9 @@ CodeGenTypes::arrangeObjCMessageSendSign
RequiredArgs required =
(MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All);
- return arrangeLLVMFunctionInfo(GetReturnType(MD->getReturnType()), false,
- argTys, einfo, required);
+ return arrangeLLVMFunctionInfo(
+ GetReturnType(MD->getReturnType()), /*instanceMethod=*/false,
+ /*chainCall=*/false, argTys, einfo, required);
}
const CGFunctionInfo &
@@ -335,7 +344,8 @@ CodeGenTypes::arrangeMSMemberPointerThun
assert(MD->isVirtual() && "only virtual memptrs have thunks");
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) };
- return arrangeLLVMFunctionInfo(Context.VoidTy, false, ArgTys,
+ return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false,
+ /*chainCall=*/false, ArgTys,
FTP->getExtInfo(), RequiredArgs(1));
}
@@ -346,7 +356,8 @@ arrangeFreeFunctionLikeCall(CodeGenTypes
CodeGenModule &CGM,
const CallArgList &args,
const FunctionType *fnType,
- unsigned numExtraRequiredArgs) {
+ unsigned numExtraRequiredArgs,
+ bool chainCall) {
assert(args.size() >= numExtraRequiredArgs);
// In most cases, there are no optional arguments.
@@ -368,8 +379,13 @@ arrangeFreeFunctionLikeCall(CodeGenTypes
required = RequiredArgs(args.size());
}
- return CGT.arrangeFreeFunctionCall(fnType->getReturnType(), args,
- fnType->getExtInfo(), required);
+ // FIXME: Kill copy.
+ SmallVector<CanQualType, 16> argTypes;
+ for (const auto &arg : args)
+ argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty));
+ return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()),
+ /*instanceMethod=*/false, chainCall,
+ argTypes, fnType->getExtInfo(), required);
}
/// Figure out the rules for calling a function with the given formal
@@ -378,8 +394,10 @@ arrangeFreeFunctionLikeCall(CodeGenTypes
/// target-dependent in crazy ways.
const CGFunctionInfo &
CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
- const FunctionType *fnType) {
- return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 0);
+ const FunctionType *fnType,
+ bool chainCall) {
+ return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType,
+ chainCall ? 1 : 0, chainCall);
}
/// A block function call is essentially a free-function call with an
@@ -387,7 +405,8 @@ CodeGenTypes::arrangeFreeFunctionCall(co
const CGFunctionInfo &
CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args,
const FunctionType *fnType) {
- return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 1);
+ return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 1,
+ /*chainCall=*/false);
}
const CGFunctionInfo &
@@ -399,8 +418,9 @@ CodeGenTypes::arrangeFreeFunctionCall(Qu
SmallVector<CanQualType, 16> argTypes;
for (const auto &Arg : args)
argTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
- return arrangeLLVMFunctionInfo(GetReturnType(resultType), false, argTypes,
- info, required);
+ return arrangeLLVMFunctionInfo(
+ GetReturnType(resultType), /*instanceMethod=*/false,
+ /*chainCall=*/false, argTypes, info, required);
}
/// Arrange a call to a C++ method, passing the given arguments.
@@ -414,8 +434,9 @@ CodeGenTypes::arrangeCXXMethodCall(const
argTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
FunctionType::ExtInfo info = FPT->getExtInfo();
- return arrangeLLVMFunctionInfo(GetReturnType(FPT->getReturnType()), true,
- argTypes, info, required);
+ return arrangeLLVMFunctionInfo(
+ GetReturnType(FPT->getReturnType()), /*instanceMethod=*/true,
+ /*chainCall=*/false, argTypes, info, required);
}
const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionDeclaration(
@@ -428,13 +449,15 @@ const CGFunctionInfo &CodeGenTypes::arra
RequiredArgs required =
(isVariadic ? RequiredArgs(args.size()) : RequiredArgs::All);
- return arrangeLLVMFunctionInfo(GetReturnType(resultType), false, argTypes, info,
- required);
+ return arrangeLLVMFunctionInfo(
+ GetReturnType(resultType), /*instanceMethod=*/false,
+ /*chainCall=*/false, argTypes, info, required);
}
const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
- return arrangeLLVMFunctionInfo(getContext().VoidTy, false, None,
- FunctionType::ExtInfo(), RequiredArgs::All);
+ return arrangeLLVMFunctionInfo(
+ getContext().VoidTy, /*instanceMethod=*/false, /*chainCall=*/false,
+ None, FunctionType::ExtInfo(), RequiredArgs::All);
}
/// Arrange the argument and result information for an abstract value
@@ -442,7 +465,8 @@ const CGFunctionInfo &CodeGenTypes::arra
/// above functions ultimately defer to.
const CGFunctionInfo &
CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
- bool IsInstanceMethod,
+ bool instanceMethod,
+ bool chainCall,
ArrayRef<CanQualType> argTypes,
FunctionType::ExtInfo info,
RequiredArgs required) {
@@ -453,8 +477,8 @@ CodeGenTypes::arrangeLLVMFunctionInfo(Ca
// Lookup or create unique function info.
llvm::FoldingSetNodeID ID;
- CGFunctionInfo::Profile(ID, IsInstanceMethod, info, required, resultType,
- argTypes);
+ CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, required,
+ resultType, argTypes);
void *insertPos = nullptr;
CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
@@ -462,8 +486,8 @@ CodeGenTypes::arrangeLLVMFunctionInfo(Ca
return *FI;
// Construct the function info. We co-allocate the ArgInfos.
- FI = CGFunctionInfo::create(CC, IsInstanceMethod, info, resultType, argTypes,
- required);
+ FI = CGFunctionInfo::create(CC, instanceMethod, chainCall, info,
+ resultType, argTypes, required);
FunctionInfos.InsertNode(FI, insertPos);
bool inserted = FunctionsBeingProcessed.insert(FI).second;
@@ -491,7 +515,8 @@ CodeGenTypes::arrangeLLVMFunctionInfo(Ca
}
CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC,
- bool IsInstanceMethod,
+ bool instanceMethod,
+ bool chainCall,
const FunctionType::ExtInfo &info,
CanQualType resultType,
ArrayRef<CanQualType> argTypes,
@@ -502,7 +527,8 @@ CGFunctionInfo *CGFunctionInfo::create(u
FI->CallingConvention = llvmCC;
FI->EffectiveCallingConvention = llvmCC;
FI->ASTCallingConvention = info.getCC();
- FI->InstanceMethod = IsInstanceMethod;
+ FI->InstanceMethod = instanceMethod;
+ FI->ChainCall = chainCall;
FI->NoReturn = info.getNoReturn();
FI->ReturnsRetained = info.getProducesResult();
FI->Required = required;
@@ -1497,7 +1523,6 @@ void CodeGenModule::ConstructAttributeLi
getLLVMContext(), IRFunctionArgs.getInallocaArgNo() + 1, Attrs));
}
-
unsigned ArgNo = 0;
for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(),
E = FI.arg_end();
@@ -1525,7 +1550,9 @@ void CodeGenModule::ConstructAttributeLi
Attrs.addAttribute(llvm::Attribute::ZExt);
// FALL THROUGH
case ABIArgInfo::Direct:
- if (AI.getInReg())
+ if (ArgNo == 0 && FI.isChainCall())
+ Attrs.addAttribute(llvm::Attribute::Nest);
+ else if (AI.getInReg())
Attrs.addAttribute(llvm::Attribute::InReg);
break;
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Dec 12 17:41:25 2014
@@ -3049,7 +3049,7 @@ RValue CodeGenFunction::EmitCallExpr(con
const Decl *TargetDecl = E->getCalleeDecl();
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
if (unsigned builtinID = FD->getBuiltinID())
- return EmitBuiltinExpr(FD, builtinID, E);
+ return EmitBuiltinExpr(FD, builtinID, E, ReturnValue);
}
if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(E))
@@ -3286,7 +3286,7 @@ LValue CodeGenFunction::EmitStmtExprLVal
RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
const CallExpr *E, ReturnValueSlot ReturnValue,
- const Decl *TargetDecl) {
+ const Decl *TargetDecl, 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() &&
@@ -3351,12 +3351,15 @@ RValue CodeGenFunction::EmitCall(QualTyp
}
CallArgList Args;
+ if (Chain)
+ Args.add(RValue::get(Builder.CreateBitCast(Chain, CGM.VoidPtrTy)),
+ CGM.getContext().VoidPtrTy);
EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), E->arg_begin(),
E->arg_end(), E->getDirectCallee(), /*ParamsToSkip*/ 0,
ForceColumnInfo);
- const CGFunctionInfo &FnInfo =
- CGM.getTypes().arrangeFreeFunctionCall(Args, FnType);
+ const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(
+ Args, FnType, /*isChainCall=*/Chain);
// C99 6.5.2.2p6:
// If the expression that denotes the called function has a type
@@ -3375,7 +3378,10 @@ RValue CodeGenFunction::EmitCall(QualTyp
// through an unprototyped function type works like a *non-variadic*
// call. The way we make this work is to cast to the exact type
// of the promoted arguments.
- if (isa<FunctionNoProtoType>(FnType)) {
+ //
+ // Chain calls use this same code path to add the invisible chain parameter
+ // to the function type.
+ if (isa<FunctionNoProtoType>(FnType) || Chain) {
llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo);
CalleeTy = CalleeTy->getPointerTo();
Callee = Builder.CreateBitCast(Callee, CalleeTy, "callee.knr.cast");
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Fri Dec 12 17:41:25 2014
@@ -1037,9 +1037,9 @@ static RValue EmitNewDeleteCall(CodeGenF
llvm::Instruction *CallOrInvoke;
llvm::Value *CalleeAddr = CGF.CGM.GetAddrOfFunction(Callee);
RValue RV =
- CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(Args, CalleeType),
- CalleeAddr, ReturnValueSlot(), Args,
- Callee, &CallOrInvoke);
+ CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
+ Args, CalleeType, /*chainCall=*/false),
+ CalleeAddr, ReturnValueSlot(), Args, Callee, &CallOrInvoke);
/// C++1y [expr.new]p10:
/// [In a new-expression,] an implementation is allowed to omit a call
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Fri Dec 12 17:41:25 2014
@@ -244,9 +244,9 @@ public:
Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Params.push_back(Ctx.BoolTy);
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(IdType, false, Params,
- FunctionType::ExtInfo(),
- RequiredArgs::All));
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
+ IdType, false, false, Params, FunctionType::ExtInfo(),
+ RequiredArgs::All));
return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
}
@@ -264,10 +264,9 @@ public:
Params.push_back(Ctx.BoolTy);
Params.push_back(Ctx.BoolTy);
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
- Params,
- FunctionType::ExtInfo(),
- RequiredArgs::All));
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
+ Ctx.VoidTy, false, false, Params, FunctionType::ExtInfo(),
+ RequiredArgs::All));
return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
}
@@ -291,10 +290,9 @@ public:
Params.push_back(IdType);
Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
- Params,
- FunctionType::ExtInfo(),
- RequiredArgs::All));
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
+ Ctx.VoidTy, false, false, Params, FunctionType::ExtInfo(),
+ RequiredArgs::All));
const char *name;
if (atomic && copy)
name = "objc_setProperty_atomic_copy";
@@ -319,10 +317,9 @@ public:
Params.push_back(Ctx.BoolTy);
Params.push_back(Ctx.BoolTy);
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
- Params,
- FunctionType::ExtInfo(),
- RequiredArgs::All));
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
+ Ctx.VoidTy, false, false, Params, FunctionType::ExtInfo(),
+ RequiredArgs::All));
return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
}
@@ -339,7 +336,7 @@ public:
Params.push_back(Ctx.VoidPtrTy);
Params.push_back(Ctx.VoidPtrTy);
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false, false,
Params,
FunctionType::ExtInfo(),
RequiredArgs::All));
@@ -353,10 +350,9 @@ public:
SmallVector<CanQualType,1> Params;
Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
- Params,
- FunctionType::ExtInfo(),
- RequiredArgs::All));
+ Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
+ Ctx.VoidTy, false, false, Params, FunctionType::ExtInfo(),
+ RequiredArgs::All));
return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
}
Modified: cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenABITypes.cpp Fri Dec 12 17:41:25 2014
@@ -67,5 +67,6 @@ CodeGenABITypes::arrangeFreeFunctionCall
FunctionType::ExtInfo info,
RequiredArgs args) {
return CGM->getTypes().arrangeLLVMFunctionInfo(
- returnType, /*IsInstanceMethod=*/false, argTypes, info, args);
+ returnType, /*IsInstanceMethod=*/false, /*IsChainCall=*/false, argTypes,
+ info, args);
}
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Dec 12 17:41:25 2014
@@ -2284,7 +2284,8 @@ public:
RValue EmitCall(QualType FnType, llvm::Value *Callee, const CallExpr *E,
ReturnValueSlot ReturnValue,
- const Decl *TargetDecl = nullptr);
+ const Decl *TargetDecl = nullptr,
+ llvm::Value *Chain = nullptr);
RValue EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue = ReturnValueSlot());
@@ -2351,7 +2352,8 @@ public:
RValue EmitBuiltinExpr(const FunctionDecl *FD,
- unsigned BuiltinID, const CallExpr *E);
+ unsigned BuiltinID, const CallExpr *E,
+ ReturnValueSlot ReturnValue);
RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue);
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Fri Dec 12 17:41:25 2014
@@ -248,7 +248,8 @@ public:
CXXCtorType CtorKind,
unsigned ExtraArgs);
const CGFunctionInfo &arrangeFreeFunctionCall(const CallArgList &Args,
- const FunctionType *Ty);
+ const FunctionType *Ty,
+ bool ChainCall);
const CGFunctionInfo &arrangeFreeFunctionCall(QualType ResTy,
const CallArgList &args,
FunctionType::ExtInfo info,
@@ -273,7 +274,8 @@ public:
///
/// \param argTypes - must all actually be canonical as params
const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType,
- bool IsInstanceMethod,
+ bool instanceMethod,
+ bool chainCall,
ArrayRef<CanQualType> argTypes,
FunctionType::ExtInfo info,
RequiredArgs args);
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Fri Dec 12 17:41:25 2014
@@ -1146,6 +1146,10 @@ void X86_32ABIInfo::computeInfo(CGFuncti
}
}
+ // The chain argument effectively gives us another free register.
+ if (FI.isChainCall())
+ ++State.FreeRegs;
+
bool UsedInAlloca = false;
for (auto &I : FI.arguments()) {
I.info = classifyArgumentType(I.type, State);
@@ -2687,6 +2691,10 @@ void X86_64ABIInfo::computeInfo(CGFuncti
if (FI.getReturnInfo().isIndirect())
--freeIntRegs;
+ // The chain argument effectively gives us another free register.
+ if (FI.isChainCall())
+ ++freeIntRegs;
+
unsigned NumRequiredArgs = FI.getNumRequiredArgs();
// AMD64-ABI 3.2.3p3: Once arguments are classified, the registers
// get assigned (in left-to-right order) for passing as follows...
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=224167&r1=224166&r2=224167&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Dec 12 17:41:25 2014
@@ -139,6 +139,69 @@ static void SemaBuiltinMemChkCall(Sema &
S.Diag(SL, diag::warn_memcpy_chk_overflow) << SR << FnName;
}
+static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) {
+ if (checkArgCount(S, BuiltinCall, 2))
+ return true;
+
+ SourceLocation BuiltinLoc = BuiltinCall->getLocStart();
+ Expr *Builtin = BuiltinCall->getCallee()->IgnoreImpCasts();
+ Expr *Call = BuiltinCall->getArg(0);
+ Expr *Chain = BuiltinCall->getArg(1);
+
+ if (Call->getStmtClass() != Stmt::CallExprClass) {
+ S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_not_call)
+ << Call->getSourceRange();
+ return true;
+ }
+
+ auto CE = cast<CallExpr>(Call);
+ if (CE->getCallee()->getType()->isBlockPointerType()) {
+ S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_block_call)
+ << Call->getSourceRange();
+ return true;
+ }
+
+ const Decl *TargetDecl = CE->getCalleeDecl();
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
+ if (FD->getBuiltinID()) {
+ S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_builtin_call)
+ << Call->getSourceRange();
+ return true;
+ }
+
+ if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) {
+ S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_pdtor_call)
+ << Call->getSourceRange();
+ return true;
+ }
+
+ ExprResult ChainResult = S.UsualUnaryConversions(Chain);
+ if (ChainResult.isInvalid())
+ return true;
+ if (!ChainResult.get()->getType()->isPointerType()) {
+ S.Diag(BuiltinLoc, diag::err_second_argument_to_cwsc_not_pointer)
+ << Chain->getSourceRange();
+ return true;
+ }
+
+ QualType ReturnTy = CE->getCallReturnType();
+ QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() };
+ QualType BuiltinTy = S.Context.getFunctionType(
+ ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo());
+ QualType BuiltinPtrTy = S.Context.getPointerType(BuiltinTy);
+
+ Builtin =
+ S.ImpCastExprToType(Builtin, BuiltinPtrTy, CK_BuiltinFnToFnPtr).get();
+
+ BuiltinCall->setType(CE->getType());
+ BuiltinCall->setValueKind(CE->getValueKind());
+ BuiltinCall->setObjectKind(CE->getObjectKind());
+ BuiltinCall->setCallee(Builtin);
+ BuiltinCall->setArg(1, ChainResult.get());
+
+ return false;
+}
+
ExprResult
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
CallExpr *TheCall) {
@@ -393,6 +456,11 @@ Sema::CheckBuiltinFunctionCall(FunctionD
case Builtin::BI__builtin___vsnprintf_chk:
SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3);
break;
+
+ case Builtin::BI__builtin_call_with_static_chain:
+ if (SemaBuiltinCallWithStaticChain(*this, TheCall))
+ return ExprError();
+ break;
}
// Since the target specific builtins for each arch overlap, only check those
Added: cfe/trunk/test/CodeGenCXX/call-with-static-chain.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/call-with-static-chain.cpp?rev=224167&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/call-with-static-chain.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/call-with-static-chain.cpp Fri Dec 12 17:41:25 2014
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck -check-prefix=CHECK32 %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck -check-prefix=CHECK64 %s
+
+struct A {
+ long x, y;
+};
+
+struct B {
+ long x, y, z, w;
+};
+
+extern "C" {
+
+int f1(A, A, A, A);
+B f2(void);
+_Complex float f3(void);
+A &f4();
+
+}
+
+void test() {
+ A a;
+
+ // CHECK32: call i32 bitcast (i32 (%struct.A*, %struct.A*, %struct.A*, %struct.A*)* @f1 to i32 (i8*, %struct.A*, %struct.A*, %struct.A*, %struct.A*)*)(i8* nest bitcast (i32 (%struct.A*, %struct.A*, %struct.A*, %struct.A*)* @f1 to i8*)
+ // CHECK64: call i32 bitcast (i32 (i64, i64, i64, i64, i64, i64, %struct.A*)* @f1 to i32 (i8*, i64, i64, i64, i64, i64, i64, %struct.A*)*)(i8* nest bitcast (i32 (i64, i64, i64, i64, i64, i64, %struct.A*)* @f1 to i8*)
+ __builtin_call_with_static_chain(f1(a, a, a, a), f1);
+
+ // CHECK32: call void bitcast (void (%struct.B*)* @f2 to void (%struct.B*, i8*)*)(%struct.B* sret %{{[0-9a-z]+}}, i8* nest bitcast (void (%struct.B*)* @f2 to i8*))
+ // CHECK64: call void bitcast (void (%struct.B*)* @f2 to void (%struct.B*, i8*)*)(%struct.B* sret %{{[0-9a-z]+}}, i8* nest bitcast (void (%struct.B*)* @f2 to i8*))
+ __builtin_call_with_static_chain(f2(), f2);
+
+ // CHECK32: call i64 bitcast (i64 ()* @f3 to i64 (i8*)*)(i8* nest bitcast (i64 ()* @f3 to i8*))
+ // CHECK64: call <2 x float> bitcast (<2 x float> ()* @f3 to <2 x float> (i8*)*)(i8* nest bitcast (<2 x float> ()* @f3 to i8*))
+ __builtin_call_with_static_chain(f3(), f3);
+
+ // CHECK32: call dereferenceable(8) %struct.A* bitcast (%struct.A* ()* @f4 to %struct.A* (i8*)*)(i8* nest bitcast (%struct.A* ()* @f4 to i8*))
+ // CHECK64: call dereferenceable(16) %struct.A* bitcast (%struct.A* ()* @f4 to %struct.A* (i8*)*)(i8* nest bitcast (%struct.A* ()* @f4 to i8*))
+ __builtin_call_with_static_chain(f4(), f4);
+}
Added: cfe/trunk/test/Sema/call-with-static-chain.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/call-with-static-chain.c?rev=224167&view=auto
==============================================================================
--- cfe/trunk/test/Sema/call-with-static-chain.c (added)
+++ cfe/trunk/test/Sema/call-with-static-chain.c Fri Dec 12 17:41:25 2014
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
+
+void f();
+
+void g() {
+ __builtin_call_with_static_chain(f(), f);
+ __builtin_call_with_static_chain(f, f); // expected-error {{first argument to __builtin_call_with_static_chain must be a non-member call expression}}
+ __builtin_call_with_static_chain(^{}(), f); // expected-error {{first argument to __builtin_call_with_static_chain must not be a block call}}
+ __builtin_call_with_static_chain(__builtin_unreachable(), f); // expected-error {{first argument to __builtin_call_with_static_chain must not be a builtin call}}
+ __builtin_call_with_static_chain(f(), 42); // expected-error {{second argument to __builtin_call_with_static_chain must be of pointer type}}
+}
Added: cfe/trunk/test/SemaCXX/call-with-static-chain.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/call-with-static-chain.cpp?rev=224167&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/call-with-static-chain.cpp (added)
+++ cfe/trunk/test/SemaCXX/call-with-static-chain.cpp Fri Dec 12 17:41:25 2014
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int &f();
+
+struct A {
+ void f();
+};
+
+typedef int I;
+
+void g() {
+ __builtin_call_with_static_chain(f(), f) = 42;
+ __builtin_call_with_static_chain(A().f(), f); // expected-error {{first argument to __builtin_call_with_static_chain must be a non-member call expression}}
+ __builtin_call_with_static_chain((42).~I(), f); // expected-error {{first argument to __builtin_call_with_static_chain must not be a pseudo-destructor call}}
+}
More information about the cfe-commits
mailing list