Refactor call emission to package the function pointer together with

abstract information about the callee.  NFC.

The goal here is to make it easier to recognize indirect calls and
trigger additional logic in certain cases.  That logic will come in
a later patch; in the meantime, I felt that this was a significant
improvement to the code.

llvm-svn: 285258
This commit is contained in:
John McCall 2016-10-26 23:46:34 +00:00
parent 48ef6ca0c3
commit b92ab1afd5
26 changed files with 638 additions and 359 deletions

View File

@ -445,6 +445,11 @@ public:
return const_cast<Expr*>(this)->getSourceBitField(); return const_cast<Expr*>(this)->getSourceBitField();
} }
Decl *getReferencedDeclOfCallee();
const Decl *getReferencedDeclOfCallee() const {
return const_cast<Expr*>(this)->getReferencedDeclOfCallee();
}
/// \brief If this expression is an l-value for an Objective C /// \brief If this expression is an l-value for an Objective C
/// property, find the underlying property reference expression. /// property, find the underlying property reference expression.
const ObjCPropertyRefExpr *getObjCProperty() const; const ObjCPropertyRefExpr *getObjCProperty() const;

View File

@ -664,29 +664,6 @@ public:
} }
}; };
/// CGCalleeInfo - Class to encapsulate the information about a callee to be
/// used during the generation of call/invoke instructions.
class CGCalleeInfo {
/// \brief The function proto type of the callee.
const FunctionProtoType *CalleeProtoTy;
/// \brief The function declaration of the callee.
const Decl *CalleeDecl;
public:
explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {}
CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl)
: CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
: CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {}
CGCalleeInfo(const Decl *calleeDecl)
: CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
const FunctionProtoType *getCalleeFunctionProtoType() {
return CalleeProtoTy;
}
const Decl *getCalleeDecl() { return CalleeDecl; }
};
} // end namespace CodeGen } // end namespace CodeGen
} // end namespace clang } // end namespace clang

View File

@ -1181,8 +1181,16 @@ void CallExpr::updateDependenciesFromArg(Expr *Arg) {
ExprBits.ContainsUnexpandedParameterPack = true; ExprBits.ContainsUnexpandedParameterPack = true;
} }
FunctionDecl *CallExpr::getDirectCallee() {
return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
}
Decl *CallExpr::getCalleeDecl() { Decl *CallExpr::getCalleeDecl() {
Expr *CEE = getCallee()->IgnoreParenImpCasts(); return getCallee()->getReferencedDeclOfCallee();
}
Decl *Expr::getReferencedDeclOfCallee() {
Expr *CEE = IgnoreParenImpCasts();
while (SubstNonTypeTemplateParmExpr *NTTP while (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) { = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
@ -1205,10 +1213,6 @@ Decl *CallExpr::getCalleeDecl() {
return nullptr; return nullptr;
} }
FunctionDecl *CallExpr::getDirectCallee() {
return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
}
/// setNumArgs - This changes the number of arguments present in this call. /// setNumArgs - This changes the number of arguments present in this call.
/// Any orphaned expressions are deleted by this, and any new operands are set /// Any orphaned expressions are deleted by this, and any new operands are set
/// to null. /// to null.

View File

@ -307,7 +307,8 @@ static RValue emitAtomicLibcall(CodeGenFunction &CGF,
CGF.CGM.getTypes().arrangeBuiltinFunctionCall(resultType, args); CGF.CGM.getTypes().arrangeBuiltinFunctionCall(resultType, args);
llvm::FunctionType *fnTy = CGF.CGM.getTypes().GetFunctionType(fnInfo); llvm::FunctionType *fnTy = CGF.CGM.getTypes().GetFunctionType(fnInfo);
llvm::Constant *fn = CGF.CGM.CreateRuntimeFunction(fnTy, fnName); llvm::Constant *fn = CGF.CGM.CreateRuntimeFunction(fnTy, fnName);
return CGF.EmitCall(fnInfo, fn, ReturnValueSlot(), args); auto callee = CGCallee::forDirect(fn);
return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args);
} }
/// Does a store of the given IR type modify the full expected width? /// Does a store of the given IR type modify the full expected width?

View File

@ -975,25 +975,24 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
const BlockPointerType *BPT = const BlockPointerType *BPT =
E->getCallee()->getType()->getAs<BlockPointerType>(); E->getCallee()->getType()->getAs<BlockPointerType>();
llvm::Value *Callee = EmitScalarExpr(E->getCallee()); llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee());
// Get a pointer to the generic block literal. // Get a pointer to the generic block literal.
llvm::Type *BlockLiteralTy = llvm::Type *BlockLiteralTy =
llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType()); llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
// Bitcast the callee to a block literal. // Bitcast the callee to a block literal.
llvm::Value *BlockLiteral = BlockPtr = Builder.CreateBitCast(BlockPtr, BlockLiteralTy, "block.literal");
Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
// Get the function pointer from the literal. // Get the function pointer from the literal.
llvm::Value *FuncPtr = llvm::Value *FuncPtr =
Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockLiteral, 3); Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, 3);
BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy); BlockPtr = Builder.CreateBitCast(BlockPtr, VoidPtrTy);
// Add the block literal. // Add the block literal.
CallArgList Args; CallArgList Args;
Args.add(RValue::get(BlockLiteral), getContext().VoidPtrTy); Args.add(RValue::get(BlockPtr), getContext().VoidPtrTy);
QualType FnType = BPT->getPointeeType(); QualType FnType = BPT->getPointeeType();
@ -1013,8 +1012,11 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
Func = Builder.CreateBitCast(Func, BlockFTyPtr); Func = Builder.CreateBitCast(Func, BlockFTyPtr);
// Prepare the callee.
CGCallee Callee(CGCalleeInfo(), Func);
// And call the block. // And call the block.
return EmitCall(FnInfo, Func, ReturnValue, Args); return EmitCall(FnInfo, Callee, ReturnValue, Args);
} }
Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable, Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,

View File

@ -37,8 +37,8 @@ using namespace llvm;
/// getBuiltinLibFunction - Given a builtin id for a function like /// getBuiltinLibFunction - Given a builtin id for a function like
/// "__builtin_fabsf", return a Function* for "fabsf". /// "__builtin_fabsf", return a Function* for "fabsf".
llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD, llvm::Constant *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
unsigned BuiltinID) { unsigned BuiltinID) {
assert(Context.BuiltinInfo.isLibFunction(BuiltinID)); assert(Context.BuiltinInfo.isLibFunction(BuiltinID));
// Get the name, skip over the __builtin_ prefix (if necessary). // Get the name, skip over the __builtin_ prefix (if necessary).
@ -304,10 +304,10 @@ static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) {
return CGF.Builder.CreateICmpSLT(V, Zero); return CGF.Builder.CreateICmpSLT(V, Zero);
} }
static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *Fn, static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *FD,
const CallExpr *E, llvm::Value *calleeValue) { const CallExpr *E, llvm::Constant *calleeValue) {
return CGF.EmitCall(E->getCallee()->getType(), calleeValue, E, CGCallee callee = CGCallee::forDirect(calleeValue, FD);
ReturnValueSlot(), Fn); return CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot());
} }
/// \brief Emit a call to llvm.{sadd,uadd,ssub,usub,smul,umul}.with.overflow.* /// \brief Emit a call to llvm.{sadd,uadd,ssub,usub,smul,umul}.with.overflow.*
@ -1570,7 +1570,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
CGM.getTypes().arrangeBuiltinFunctionCall(E->getType(), Args); CGM.getTypes().arrangeBuiltinFunctionCall(E->getType(), Args);
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo);
llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName); llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName);
return EmitCall(FuncInfo, Func, ReturnValueSlot(), Args); return EmitCall(FuncInfo, CGCallee::forDirect(Func),
ReturnValueSlot(), Args);
} }
case Builtin::BI__atomic_test_and_set: { case Builtin::BI__atomic_test_and_set: {
@ -2085,8 +2086,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
const CallExpr *Call = cast<CallExpr>(E->getArg(0)); const CallExpr *Call = cast<CallExpr>(E->getArg(0));
const Expr *Chain = E->getArg(1); const Expr *Chain = E->getArg(1);
return EmitCall(Call->getCallee()->getType(), return EmitCall(Call->getCallee()->getType(),
EmitScalarExpr(Call->getCallee()), Call, ReturnValue, EmitCallee(Call->getCallee()), Call, ReturnValue,
Call->getCalleeDecl(), EmitScalarExpr(Chain)); EmitScalarExpr(Chain));
} }
case Builtin::BI_InterlockedExchange8: case Builtin::BI_InterlockedExchange8:
case Builtin::BI_InterlockedExchange16: case Builtin::BI_InterlockedExchange16:
@ -2692,7 +2693,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// If this is a predefined lib function (e.g. malloc), emit the call // If this is a predefined lib function (e.g. malloc), emit the call
// using exactly the normal call path. // using exactly the normal call path.
if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return emitLibraryCall(*this, FD, E, EmitScalarExpr(E->getCallee())); return emitLibraryCall(*this, FD, E,
cast<llvm::Constant>(EmitScalarExpr(E->getCallee())));
// Check that a call to a target specific builtin has the correct target // Check that a call to a target specific builtin has the correct target
// features. // features.

View File

@ -36,16 +36,7 @@ RValue CGCUDARuntime::EmitCUDAKernelCallExpr(CodeGenFunction &CGF,
eval.begin(CGF); eval.begin(CGF);
CGF.EmitBlock(ConfigOKBlock); CGF.EmitBlock(ConfigOKBlock);
CGF.EmitSimpleCallExpr(E, ReturnValue);
const Decl *TargetDecl = nullptr;
if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E->getCallee())) {
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
TargetDecl = DRE->getDecl();
}
}
llvm::Value *Callee = CGF.EmitScalarExpr(E->getCallee());
CGF.EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue, TargetDecl);
CGF.EmitBranch(ContBlock); CGF.EmitBranch(ContBlock);
CGF.EmitBlock(ContBlock); CGF.EmitBlock(ContBlock);

View File

@ -258,10 +258,10 @@ llvm::Constant *CodeGenModule::getAddrOfCXXStructor(
/*isThunk=*/false, /*ExtraAttrs=*/llvm::AttributeSet(), IsForDefinition); /*isThunk=*/false, /*ExtraAttrs=*/llvm::AttributeSet(), IsForDefinition);
} }
static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF, static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,
GlobalDecl GD, GlobalDecl GD,
llvm::Type *Ty, llvm::Type *Ty,
const CXXRecordDecl *RD) { const CXXRecordDecl *RD) {
assert(!CGF.CGM.getTarget().getCXXABI().isMicrosoft() && assert(!CGF.CGM.getTarget().getCXXABI().isMicrosoft() &&
"No kext in Microsoft ABI"); "No kext in Microsoft ABI");
GD = GD.getCanonicalDecl(); GD = GD.getCanonicalDecl();
@ -277,16 +277,19 @@ static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
VTableIndex += AddressPoint; VTableIndex += AddressPoint;
llvm::Value *VFuncPtr = llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
return CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.PointerAlignInBytes); llvm::Value *VFunc =
CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.PointerAlignInBytes);
CGCallee Callee(GD.getDecl(), VFunc);
return Callee;
} }
/// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making /// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making
/// indirect call to virtual functions. It makes the call through indexing /// indirect call to virtual functions. It makes the call through indexing
/// into the vtable. /// into the vtable.
llvm::Value * CGCallee
CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD, CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
NestedNameSpecifier *Qual, NestedNameSpecifier *Qual,
llvm::Type *Ty) { llvm::Type *Ty) {
assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) && assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
"BuildAppleKextVirtualCall - bad Qual kind"); "BuildAppleKextVirtualCall - bad Qual kind");
@ -304,21 +307,15 @@ CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
/// BuildVirtualCall - This routine makes indirect vtable call for /// BuildVirtualCall - This routine makes indirect vtable call for
/// call to virtual destructors. It returns 0 if it could not do it. /// call to virtual destructors. It returns 0 if it could not do it.
llvm::Value * CGCallee
CodeGenFunction::BuildAppleKextVirtualDestructorCall( CodeGenFunction::BuildAppleKextVirtualDestructorCall(
const CXXDestructorDecl *DD, const CXXDestructorDecl *DD,
CXXDtorType Type, CXXDtorType Type,
const CXXRecordDecl *RD) { const CXXRecordDecl *RD) {
const auto *MD = cast<CXXMethodDecl>(DD); assert(DD->isVirtual() && Type != Dtor_Base);
// FIXME. Dtor_Base dtor is always direct!! // Compute the function type we're calling.
// It need be somehow inline expanded into the caller. const CGFunctionInfo &FInfo = CGM.getTypes().arrangeCXXStructorDeclaration(
// -O does that. But need to support -O0 as well. DD, StructorType::Complete);
if (MD->isVirtual() && Type != Dtor_Base) { llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
// Compute the function type we're calling. return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD);
const CGFunctionInfo &FInfo = CGM.getTypes().arrangeCXXStructorDeclaration(
DD, StructorType::Complete);
llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD);
}
return nullptr;
} }

View File

@ -73,7 +73,7 @@ CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
} }
llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer( CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer(
CodeGenFunction &CGF, const Expr *E, Address This, CodeGenFunction &CGF, const Expr *E, Address This,
llvm::Value *&ThisPtrForCall, llvm::Value *&ThisPtrForCall,
llvm::Value *MemPtr, const MemberPointerType *MPT) { llvm::Value *MemPtr, const MemberPointerType *MPT) {
@ -86,7 +86,8 @@ llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(
cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr));
return llvm::Constant::getNullValue(FTy->getPointerTo()); llvm::Constant *FnPtr = llvm::Constant::getNullValue(FTy->getPointerTo());
return CGCallee::forDirect(FnPtr, FPT);
} }
llvm::Value * llvm::Value *

View File

@ -35,6 +35,7 @@ class FieldDecl;
class MangleContext; class MangleContext;
namespace CodeGen { namespace CodeGen {
class CGCallee;
class CodeGenFunction; class CodeGenFunction;
class CodeGenModule; class CodeGenModule;
struct CatchTypeInfo; struct CatchTypeInfo;
@ -154,7 +155,7 @@ public:
/// Load a member function from an object and a member function /// Load a member function from an object and a member function
/// pointer. Apply the this-adjustment and set 'This' to the /// pointer. Apply the this-adjustment and set 'This' to the
/// adjusted value. /// adjusted value.
virtual llvm::Value *EmitLoadOfMemberFunctionPointer( virtual CGCallee EmitLoadOfMemberFunctionPointer(
CodeGenFunction &CGF, const Expr *E, Address This, CodeGenFunction &CGF, const Expr *E, Address This,
llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
const MemberPointerType *MPT); const MemberPointerType *MPT);
@ -403,11 +404,11 @@ public:
CharUnits VPtrOffset) = 0; CharUnits VPtrOffset) = 0;
/// Build a virtual function pointer in the ABI-specific way. /// Build a virtual function pointer in the ABI-specific way.
virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD, GlobalDecl GD,
Address This, Address This,
llvm::Type *Ty, llvm::Type *Ty,
SourceLocation Loc) = 0; SourceLocation Loc) = 0;
/// Emit the ABI-specific virtual destructor call. /// Emit the ABI-specific virtual destructor call.
virtual llvm::Value * virtual llvm::Value *

View File

@ -3519,21 +3519,22 @@ void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old,
} }
RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::Value *Callee, const CGCallee &Callee,
ReturnValueSlot ReturnValue, ReturnValueSlot ReturnValue,
const CallArgList &CallArgs, const CallArgList &CallArgs,
CGCalleeInfo CalleeInfo,
llvm::Instruction **callOrInvoke) { llvm::Instruction **callOrInvoke) {
// FIXME: We no longer need the types from CallArgs; lift up and simplify. // FIXME: We no longer need the types from CallArgs; lift up and simplify.
assert(Callee.isOrdinary());
// Handle struct-return functions by passing a pointer to the // Handle struct-return functions by passing a pointer to the
// location that we would like to return into. // location that we would like to return into.
QualType RetTy = CallInfo.getReturnType(); QualType RetTy = CallInfo.getReturnType();
const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); const ABIArgInfo &RetAI = CallInfo.getReturnInfo();
llvm::FunctionType *IRFuncTy = llvm::FunctionType *IRFuncTy = Callee.getFunctionType();
cast<llvm::FunctionType>(
cast<llvm::PointerType>(Callee->getType())->getElementType()); // 1. Set up the arguments.
// If we're using inalloca, insert the allocation after the stack save. // If we're using inalloca, insert the allocation after the stack save.
// FIXME: Do this earlier rather than hacking it in here! // FIXME: Do this earlier rather than hacking it in here!
@ -3593,6 +3594,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Address swiftErrorTemp = Address::invalid(); Address swiftErrorTemp = Address::invalid();
Address swiftErrorArg = Address::invalid(); Address swiftErrorArg = Address::invalid();
// Translate all of the arguments as necessary to match the IR lowering.
assert(CallInfo.arg_size() == CallArgs.size() && assert(CallInfo.arg_size() == CallArgs.size() &&
"Mismatch between function signature & arguments."); "Mismatch between function signature & arguments.");
unsigned ArgNo = 0; unsigned ArgNo = 0;
@ -3840,6 +3842,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
} }
} }
llvm::Value *CalleePtr = Callee.getFunctionPointer();
// If we're using inalloca, set up that argument.
if (ArgMemory.isValid()) { if (ArgMemory.isValid()) {
llvm::Value *Arg = ArgMemory.getPointer(); llvm::Value *Arg = ArgMemory.getPointer();
if (CallInfo.isVariadic()) { if (CallInfo.isVariadic()) {
@ -3847,10 +3852,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// end up with a variadic prototype and an inalloca call site. In such // end up with a variadic prototype and an inalloca call site. In such
// cases, we can't do any parameter mismatch checks. Give up and bitcast // cases, we can't do any parameter mismatch checks. Give up and bitcast
// the callee. // the callee.
unsigned CalleeAS = unsigned CalleeAS = CalleePtr->getType()->getPointerAddressSpace();
cast<llvm::PointerType>(Callee->getType())->getAddressSpace(); auto FnTy = getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS);
Callee = Builder.CreateBitCast( CalleePtr = Builder.CreateBitCast(CalleePtr, FnTy);
Callee, getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS));
} else { } else {
llvm::Type *LastParamTy = llvm::Type *LastParamTy =
IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1); IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1);
@ -3874,39 +3878,57 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg; IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg;
} }
// 2. Prepare the function pointer.
// If the callee is a bitcast of a non-variadic function to have a
// variadic function pointer type, check to see if we can remove the
// bitcast. This comes up with unprototyped functions.
//
// This makes the IR nicer, but more importantly it ensures that we
// can inline the function at -O0 if it is marked always_inline.
auto simplifyVariadicCallee = [](llvm::Value *Ptr) -> llvm::Value* {
llvm::FunctionType *CalleeFT =
cast<llvm::FunctionType>(Ptr->getType()->getPointerElementType());
if (!CalleeFT->isVarArg())
return Ptr;
llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Ptr);
if (!CE || CE->getOpcode() != llvm::Instruction::BitCast)
return Ptr;
llvm::Function *OrigFn = dyn_cast<llvm::Function>(CE->getOperand(0));
if (!OrigFn)
return Ptr;
llvm::FunctionType *OrigFT = OrigFn->getFunctionType();
// If the original type is variadic, or if any of the component types
// disagree, we cannot remove the cast.
if (OrigFT->isVarArg() ||
OrigFT->getNumParams() != CalleeFT->getNumParams() ||
OrigFT->getReturnType() != CalleeFT->getReturnType())
return Ptr;
for (unsigned i = 0, e = OrigFT->getNumParams(); i != e; ++i)
if (OrigFT->getParamType(i) != CalleeFT->getParamType(i))
return Ptr;
return OrigFn;
};
CalleePtr = simplifyVariadicCallee(CalleePtr);
// 3. Perform the actual call.
// Deactivate any cleanups that we're supposed to do immediately before
// the call.
if (!CallArgs.getCleanupsToDeactivate().empty()) if (!CallArgs.getCleanupsToDeactivate().empty())
deactivateArgCleanupsBeforeCall(*this, CallArgs); deactivateArgCleanupsBeforeCall(*this, CallArgs);
// If the callee is a bitcast of a function to a varargs pointer to function // Assert that the arguments we computed match up. The IR verifier
// type, check to see if we can remove the bitcast. This handles some cases // will catch this, but this is a common enough source of problems
// with unprototyped functions. // during IRGen changes that it's way better for debugging to catch
if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Callee)) // it ourselves here.
if (llvm::Function *CalleeF = dyn_cast<llvm::Function>(CE->getOperand(0))) { #ifndef NDEBUG
llvm::PointerType *CurPT=cast<llvm::PointerType>(Callee->getType());
llvm::FunctionType *CurFT =
cast<llvm::FunctionType>(CurPT->getElementType());
llvm::FunctionType *ActualFT = CalleeF->getFunctionType();
if (CE->getOpcode() == llvm::Instruction::BitCast &&
ActualFT->getReturnType() == CurFT->getReturnType() &&
ActualFT->getNumParams() == CurFT->getNumParams() &&
ActualFT->getNumParams() == IRCallArgs.size() &&
(CurFT->isVarArg() || !ActualFT->isVarArg())) {
bool ArgsMatch = true;
for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i)
if (ActualFT->getParamType(i) != CurFT->getParamType(i)) {
ArgsMatch = false;
break;
}
// Strip the cast if we can get away with it. This is a nice cleanup,
// but also allows us to inline the function at -O0 if it is marked
// always_inline.
if (ArgsMatch)
Callee = CalleeF;
}
}
assert(IRCallArgs.size() == IRFuncTy->getNumParams() || IRFuncTy->isVarArg()); assert(IRCallArgs.size() == IRFuncTy->getNumParams() || IRFuncTy->isVarArg());
for (unsigned i = 0; i < IRCallArgs.size(); ++i) { for (unsigned i = 0; i < IRCallArgs.size(); ++i) {
// Inalloca argument can have different type. // Inalloca argument can have different type.
@ -3916,75 +3938,106 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (i < IRFuncTy->getNumParams()) if (i < IRFuncTy->getNumParams())
assert(IRCallArgs[i]->getType() == IRFuncTy->getParamType(i)); assert(IRCallArgs[i]->getType() == IRFuncTy->getParamType(i));
} }
#endif
// Compute the calling convention and attributes.
unsigned CallingConv; unsigned CallingConv;
CodeGen::AttributeListType AttributeList; CodeGen::AttributeListType AttributeList;
CGM.ConstructAttributeList(Callee->getName(), CallInfo, CalleeInfo, CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo,
Callee.getAbstractInfo(),
AttributeList, CallingConv, AttributeList, CallingConv,
/*AttrOnCallSite=*/true); /*AttrOnCallSite=*/true);
llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(), llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(),
AttributeList); AttributeList);
// Apply some call-site-specific attributes.
// TODO: work this into building the attribute set.
// Apply always_inline to all calls within flatten functions.
// FIXME: should this really take priority over __try, below?
if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
!(Callee.getAbstractInfo().getCalleeDecl() &&
Callee.getAbstractInfo().getCalleeDecl()->hasAttr<NoInlineAttr>())) {
Attrs =
Attrs.addAttribute(getLLVMContext(),
llvm::AttributeSet::FunctionIndex,
llvm::Attribute::AlwaysInline);
}
// Disable inlining inside SEH __try blocks.
if (isSEHTryScope()) {
Attrs =
Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoInline);
}
// Decide whether to use a call or an invoke.
bool CannotThrow; bool CannotThrow;
if (currentFunctionUsesSEHTry()) { if (currentFunctionUsesSEHTry()) {
// SEH cares about asynchronous exceptions, everything can "throw." // SEH cares about asynchronous exceptions, so everything can "throw."
CannotThrow = false; CannotThrow = false;
} else if (isCleanupPadScope() && } else if (isCleanupPadScope() &&
EHPersonality::get(*this).isMSVCXXPersonality()) { EHPersonality::get(*this).isMSVCXXPersonality()) {
// The MSVC++ personality will implicitly terminate the program if an // The MSVC++ personality will implicitly terminate the program if an
// exception is thrown. An unwind edge cannot be reached. // exception is thrown during a cleanup outside of a try/catch.
// We don't need to model anything in IR to get this behavior.
CannotThrow = true; CannotThrow = true;
} else { } else {
// Otherwise, nowunind callsites will never throw. // Otherwise, nounwind call sites will never throw.
CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex, CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoUnwind); llvm::Attribute::NoUnwind);
} }
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest(); llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
SmallVector<llvm::OperandBundleDef, 1> BundleList; SmallVector<llvm::OperandBundleDef, 1> BundleList;
getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList); getBundlesForFunclet(CalleePtr, CurrentFuncletPad, BundleList);
// Emit the actual call/invoke instruction.
llvm::CallSite CS; llvm::CallSite CS;
if (!InvokeDest) { if (!InvokeDest) {
CS = Builder.CreateCall(Callee, IRCallArgs, BundleList); CS = Builder.CreateCall(CalleePtr, IRCallArgs, BundleList);
} else { } else {
llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, IRCallArgs, CS = Builder.CreateInvoke(CalleePtr, Cont, InvokeDest, IRCallArgs,
BundleList); BundleList);
EmitBlock(Cont); EmitBlock(Cont);
} }
llvm::Instruction *CI = CS.getInstruction();
if (callOrInvoke) if (callOrInvoke)
*callOrInvoke = CS.getInstruction(); *callOrInvoke = CI;
if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
!CS.hasFnAttr(llvm::Attribute::NoInline))
Attrs =
Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
llvm::Attribute::AlwaysInline);
// Disable inlining inside SEH __try blocks.
if (isSEHTryScope())
Attrs =
Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoInline);
// Apply the attributes and calling convention.
CS.setAttributes(Attrs); CS.setAttributes(Attrs);
CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
// Apply various metadata.
if (!CI->getType()->isVoidTy())
CI->setName("call");
// Insert instrumentation or attach profile metadata at indirect call sites. // Insert instrumentation or attach profile metadata at indirect call sites.
// For more details, see the comment before the definition of // For more details, see the comment before the definition of
// IPVK_IndirectCallTarget in InstrProfData.inc. // IPVK_IndirectCallTarget in InstrProfData.inc.
if (!CS.getCalledFunction()) if (!CS.getCalledFunction())
PGO.valueProfile(Builder, llvm::IPVK_IndirectCallTarget, PGO.valueProfile(Builder, llvm::IPVK_IndirectCallTarget,
CS.getInstruction(), Callee); CI, CalleePtr);
// In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
// optimizer it can aggressively ignore unwind edges. // optimizer it can aggressively ignore unwind edges.
if (CGM.getLangOpts().ObjCAutoRefCount) if (CGM.getLangOpts().ObjCAutoRefCount)
AddObjCARCExceptionMetadata(CS.getInstruction()); AddObjCARCExceptionMetadata(CI);
// Suppress tail calls if requested.
if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl();
if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
}
// 4. Finish the call.
// If the call doesn't return, finish the basic block and clear the // If the call doesn't return, finish the basic block and clear the
// insertion point; this allows the rest of IRgen to discard // insertion point; this allows the rest of IRGen to discard
// unreachable code. // unreachable code.
if (CS.doesNotReturn()) { if (CS.doesNotReturn()) {
if (UnusedReturnSize) if (UnusedReturnSize)
@ -4003,18 +4056,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
return GetUndefRValue(RetTy); return GetUndefRValue(RetTy);
} }
llvm::Instruction *CI = CS.getInstruction();
if (!CI->getType()->isVoidTy())
CI->setName("call");
// Perform the swifterror writeback. // Perform the swifterror writeback.
if (swiftErrorTemp.isValid()) { if (swiftErrorTemp.isValid()) {
llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp); llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp);
Builder.CreateStore(errorResult, swiftErrorArg); Builder.CreateStore(errorResult, swiftErrorArg);
} }
// Emit any writebacks immediately. Arguably this should happen // Emit any call-associated writebacks immediately. Arguably this
// after any return-value munging. // should happen after any return-value munging.
if (CallArgs.hasWritebacks()) if (CallArgs.hasWritebacks())
emitWritebacks(*this, CallArgs); emitWritebacks(*this, CallArgs);
@ -4022,12 +4071,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// lexical order, so deactivate it and run it manually here. // lexical order, so deactivate it and run it manually here.
CallArgs.freeArgumentMemory(*this); CallArgs.freeArgumentMemory(*this);
if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) { // Extract the return value.
const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
}
RValue Ret = [&] { RValue Ret = [&] {
switch (RetAI.getKind()) { switch (RetAI.getKind()) {
case ABIArgInfo::CoerceAndExpand: { case ABIArgInfo::CoerceAndExpand: {
@ -4124,8 +4168,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm_unreachable("Unhandled ABIArgInfo::Kind"); llvm_unreachable("Unhandled ABIArgInfo::Kind");
} (); } ();
const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); // Emit the assume_aligned check on the return value.
const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl();
if (Ret.isScalar() && TargetDecl) { if (Ret.isScalar() && TargetDecl) {
if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) { if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) {
llvm::Value *OffsetValue = nullptr; llvm::Value *OffsetValue = nullptr;

View File

@ -41,6 +41,131 @@ namespace clang {
namespace CodeGen { namespace CodeGen {
typedef SmallVector<llvm::AttributeSet, 8> AttributeListType; typedef SmallVector<llvm::AttributeSet, 8> AttributeListType;
/// Abstract information about a function or function prototype.
class CGCalleeInfo {
/// \brief The function prototype of the callee.
const FunctionProtoType *CalleeProtoTy;
/// \brief The function declaration of the callee.
const Decl *CalleeDecl;
public:
explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {}
CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl)
: CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
: CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {}
CGCalleeInfo(const Decl *calleeDecl)
: CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
const FunctionProtoType *getCalleeFunctionProtoType() const {
return CalleeProtoTy;
}
const Decl *getCalleeDecl() const { return CalleeDecl; }
};
/// All available information about a concrete callee.
class CGCallee {
enum class SpecialKind : uintptr_t {
Invalid,
Builtin,
PseudoDestructor,
Last = PseudoDestructor
};
SpecialKind KindOrFunctionPointer;
union {
CGCalleeInfo AbstractInfo;
struct {
const FunctionDecl *Decl;
unsigned ID;
} BuiltinInfo;
struct {
const CXXPseudoDestructorExpr *Expr;
} PseudoDestructorInfo;
};
explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}
CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID)
: KindOrFunctionPointer(SpecialKind::Builtin) {
BuiltinInfo.Decl = builtinDecl;
BuiltinInfo.ID = builtinID;
}
public:
CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {}
/// Construct a callee. Call this constructor directly when this
/// isn't a direct call.
CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr)
: KindOrFunctionPointer(SpecialKind(uintptr_t(functionPtr))) {
AbstractInfo = abstractInfo;
assert(functionPtr && "configuring callee without function pointer");
assert(functionPtr->getType()->isPointerTy());
assert(functionPtr->getType()->getPointerElementType()->isFunctionTy());
}
static CGCallee forBuiltin(unsigned builtinID,
const FunctionDecl *builtinDecl) {
CGCallee result(SpecialKind::Builtin);
result.BuiltinInfo.Decl = builtinDecl;
result.BuiltinInfo.ID = builtinID;
return result;
}
static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) {
CGCallee result(SpecialKind::PseudoDestructor);
result.PseudoDestructorInfo.Expr = E;
return result;
}
static CGCallee forDirect(llvm::Constant *functionPtr,
const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
return CGCallee(abstractInfo, functionPtr);
}
bool isBuiltin() const {
return KindOrFunctionPointer == SpecialKind::Builtin;
}
const FunctionDecl *getBuiltinDecl() const {
assert(isBuiltin());
return BuiltinInfo.Decl;
}
unsigned getBuiltinID() const {
assert(isBuiltin());
return BuiltinInfo.ID;
}
bool isPseudoDestructor() const {
return KindOrFunctionPointer == SpecialKind::PseudoDestructor;
}
const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {
assert(isPseudoDestructor());
return PseudoDestructorInfo.Expr;
}
bool isOrdinary() const {
return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);
}
const CGCalleeInfo &getAbstractInfo() const {
assert(isOrdinary());
return AbstractInfo;
}
llvm::Value *getFunctionPointer() const {
assert(isOrdinary());
return reinterpret_cast<llvm::Value*>(uintptr_t(KindOrFunctionPointer));
}
llvm::FunctionType *getFunctionType() const {
return cast<llvm::FunctionType>(
getFunctionPointer()->getType()->getPointerElementType());
}
void setFunctionPointer(llvm::Value *functionPtr) {
assert(isOrdinary());
KindOrFunctionPointer = SpecialKind(uintptr_t(functionPtr));
}
};
struct CallArg { struct CallArg {
RValue RV; RValue RV;
QualType Ty; QualType Ty;

View File

@ -2181,10 +2181,12 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
*this, D, Type, ForVirtualBase, Delegating, Args); *this, D, Type, ForVirtualBase, Delegating, Args);
// Emit the call. // Emit the call.
llvm::Value *Callee = CGM.getAddrOfCXXStructor(D, getFromCtorType(Type)); llvm::Constant *CalleePtr =
CGM.getAddrOfCXXStructor(D, getFromCtorType(Type));
const CGFunctionInfo &Info = const CGFunctionInfo &Info =
CGM.getTypes().arrangeCXXConstructorCall(Args, D, Type, ExtraArgs); CGM.getTypes().arrangeCXXConstructorCall(Args, D, Type, ExtraArgs);
EmitCall(Info, Callee, ReturnValueSlot(), Args, D); CGCallee Callee = CGCallee::forDirect(CalleePtr, D);
EmitCall(Info, Callee, ReturnValueSlot(), Args);
// Generate vtable assumptions if we're constructing a complete object // Generate vtable assumptions if we're constructing a complete object
// with a vtable. We don't do this for base subobjects for two reasons: // with a vtable. We don't do this for base subobjects for two reasons:
@ -2944,7 +2946,7 @@ void CodeGenFunction::EmitForwardingCallToLambda(
// Get the address of the call operator. // Get the address of the call operator.
const CGFunctionInfo &calleeFnInfo = const CGFunctionInfo &calleeFnInfo =
CGM.getTypes().arrangeCXXMethodDeclaration(callOperator); CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);
llvm::Value *callee = llvm::Constant *calleePtr =
CGM.GetAddrOfFunction(GlobalDecl(callOperator), CGM.GetAddrOfFunction(GlobalDecl(callOperator),
CGM.getTypes().GetFunctionType(calleeFnInfo)); CGM.getTypes().GetFunctionType(calleeFnInfo));
@ -2963,8 +2965,8 @@ void CodeGenFunction::EmitForwardingCallToLambda(
// variadic arguments. // variadic arguments.
// Now emit our call. // Now emit our call.
RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, auto callee = CGCallee::forDirect(calleePtr, callOperator);
callArgs, callOperator); RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs);
// If necessary, copy the returned value into the slot. // If necessary, copy the returned value into the slot.
if (!resultType->isVoidType() && returnSlot.isNull()) if (!resultType->isVoidType() && returnSlot.isNull())

View File

@ -535,7 +535,8 @@ namespace {
CallArgList Args; CallArgList Args;
Args.add(RValue::get(Arg), Args.add(RValue::get(Arg),
CGF.getContext().getPointerType(Var.getType())); CGF.getContext().getPointerType(Var.getType()));
CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args); auto Callee = CGCallee::forDirect(CleanupFn);
CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args);
} }
}; };
} // end anonymous namespace } // end anonymous namespace

View File

@ -1433,7 +1433,8 @@ struct PerformSEHFinally final : EHScopeStack::Cleanup {
const CGFunctionInfo &FnInfo = const CGFunctionInfo &FnInfo =
CGM.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, Args); CGM.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, Args);
CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args); auto Callee = CGCallee::forDirect(OutlinedFinally);
CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args);
} }
}; };
} // end anonymous namespace } // end anonymous namespace

View File

@ -2025,9 +2025,14 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
return LV; return LV;
} }
static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, static llvm::Constant *EmitFunctionDeclPointer(CodeGenModule &CGM,
const Expr *E, const FunctionDecl *FD) { const FunctionDecl *FD) {
llvm::Value *V = CGF.CGM.GetAddrOfFunction(FD); if (FD->hasAttr<WeakRefAttr>()) {
ConstantAddress aliasee = CGM.GetWeakRefReference(FD);
return aliasee.getPointer();
}
llvm::Constant *V = CGM.GetAddrOfFunction(FD);
if (!FD->hasPrototype()) { if (!FD->hasPrototype()) {
if (const FunctionProtoType *Proto = if (const FunctionProtoType *Proto =
FD->getType()->getAs<FunctionProtoType>()) { FD->getType()->getAs<FunctionProtoType>()) {
@ -2035,11 +2040,18 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
// isn't the same as the type of a use. Correct for this with a // isn't the same as the type of a use. Correct for this with a
// bitcast. // bitcast.
QualType NoProtoType = QualType NoProtoType =
CGF.getContext().getFunctionNoProtoType(Proto->getReturnType()); CGM.getContext().getFunctionNoProtoType(Proto->getReturnType());
NoProtoType = CGF.getContext().getPointerType(NoProtoType); NoProtoType = CGM.getContext().getPointerType(NoProtoType);
V = CGF.Builder.CreateBitCast(V, CGF.ConvertType(NoProtoType)); V = llvm::ConstantExpr::getBitCast(V,
CGM.getTypes().ConvertType(NoProtoType));
} }
} }
return V;
}
static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
const Expr *E, const FunctionDecl *FD) {
llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, FD);
CharUnits Alignment = CGF.getContext().getDeclAlign(FD); CharUnits Alignment = CGF.getContext().getDeclAlign(FD);
return CGF.MakeAddrLValue(V, E->getType(), Alignment, AlignmentSource::Decl); return CGF.MakeAddrLValue(V, E->getType(), Alignment, AlignmentSource::Decl);
} }
@ -3780,70 +3792,86 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
if (const auto *CE = dyn_cast<CUDAKernelCallExpr>(E)) if (const auto *CE = dyn_cast<CUDAKernelCallExpr>(E))
return EmitCUDAKernelCallExpr(CE, ReturnValue); return EmitCUDAKernelCallExpr(CE, ReturnValue);
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, ReturnValue);
}
if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(E)) if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(E))
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl)) if (const CXXMethodDecl *MD =
dyn_cast_or_null<CXXMethodDecl>(CE->getCalleeDecl()))
return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue); return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue);
if (const auto *PseudoDtor = CGCallee callee = EmitCallee(E->getCallee());
dyn_cast<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
QualType DestroyedType = PseudoDtor->getDestroyedType();
if (DestroyedType.hasStrongOrWeakObjCLifetime()) {
// Automatic Reference Counting:
// If the pseudo-expression names a retainable object with weak or
// strong lifetime, the object shall be released.
Expr *BaseExpr = PseudoDtor->getBase();
Address BaseValue = Address::invalid();
Qualifiers BaseQuals;
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. if (callee.isBuiltin()) {
if (PseudoDtor->isArrow()) { return EmitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(),
BaseValue = EmitPointerWithAlignment(BaseExpr); E, ReturnValue);
const PointerType *PTy = BaseExpr->getType()->getAs<PointerType>();
BaseQuals = PTy->getPointeeType().getQualifiers();
} else {
LValue BaseLV = EmitLValue(BaseExpr);
BaseValue = BaseLV.getAddress();
QualType BaseTy = BaseExpr->getType();
BaseQuals = BaseTy.getQualifiers();
}
switch (DestroyedType.getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
break;
case Qualifiers::OCL_Strong:
EmitARCRelease(Builder.CreateLoad(BaseValue,
PseudoDtor->getDestroyedType().isVolatileQualified()),
ARCPreciseLifetime);
break;
case Qualifiers::OCL_Weak:
EmitARCDestroyWeak(BaseValue);
break;
}
} else {
// C++ [expr.pseudo]p1:
// The result shall only be used as the operand for the function call
// operator (), and the result of such a call has type void. The only
// effect is the evaluation of the postfix-expression before the dot or
// arrow.
EmitScalarExpr(E->getCallee());
}
return RValue::get(nullptr);
} }
llvm::Value *Callee = EmitScalarExpr(E->getCallee()); if (callee.isPseudoDestructor()) {
return EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue, return EmitCXXPseudoDestructorExpr(callee.getPseudoDestructorExpr());
TargetDecl); }
return EmitCall(E->getCallee()->getType(), callee, E, ReturnValue);
}
/// Emit a CallExpr without considering whether it might be a subclass.
RValue CodeGenFunction::EmitSimpleCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
CGCallee Callee = EmitCallee(E->getCallee());
return EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue);
}
static CGCallee EmitDirectCallee(CodeGenFunction &CGF, const FunctionDecl *FD) {
if (auto builtinID = FD->getBuiltinID()) {
return CGCallee::forBuiltin(builtinID, FD);
}
llvm::Constant *calleePtr = EmitFunctionDeclPointer(CGF.CGM, FD);
return CGCallee::forDirect(calleePtr, FD);
}
CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
E = E->IgnoreParens();
// Look through function-to-pointer decay.
if (auto ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_FunctionToPointerDecay ||
ICE->getCastKind() == CK_BuiltinFnToFnPtr) {
return EmitCallee(ICE->getSubExpr());
}
// Resolve direct calls.
} else if (auto DRE = dyn_cast<DeclRefExpr>(E)) {
if (auto FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
return EmitDirectCallee(*this, FD);
}
} else if (auto ME = dyn_cast<MemberExpr>(E)) {
if (auto FD = dyn_cast<FunctionDecl>(ME->getMemberDecl())) {
EmitIgnoredExpr(ME->getBase());
return EmitDirectCallee(*this, FD);
}
// Look through template substitutions.
} else if (auto NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
return EmitCallee(NTTP->getReplacement());
// Treat pseudo-destructor calls differently.
} else if (auto PDE = dyn_cast<CXXPseudoDestructorExpr>(E)) {
return CGCallee::forPseudoDestructor(PDE);
}
// Otherwise, we have an indirect reference.
llvm::Value *calleePtr;
QualType functionType;
if (auto ptrType = E->getType()->getAs<PointerType>()) {
calleePtr = EmitScalarExpr(E);
functionType = ptrType->getPointeeType();
} else {
functionType = E->getType();
calleePtr = EmitLValue(E).getPointer();
}
assert(functionType->isFunctionType());
CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(),
E->getReferencedDeclOfCallee());
CGCallee callee(calleeInfo, calleePtr);
return callee;
} }
LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
@ -4019,22 +4047,15 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
AlignmentSource::Decl); AlignmentSource::Decl);
} }
RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee,
const CallExpr *E, ReturnValueSlot ReturnValue, const CallExpr *E, ReturnValueSlot ReturnValue,
CGCalleeInfo CalleeInfo, llvm::Value *Chain) { llvm::Value *Chain) {
// Get the actual function type. The callee type will always be a pointer to // Get the actual function type. The callee type will always be a pointer to
// function type or a block pointer type. // function type or a block pointer type.
assert(CalleeType->isFunctionPointerType() && assert(CalleeType->isFunctionPointerType() &&
"Call must have function pointer type!"); "Call must have function pointer type!");
// Preserve the non-canonical function type because things like exception const Decl *TargetDecl = OrigCallee.getAbstractInfo().getCalleeDecl();
// 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)) if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
// We can only guarantee that a function is called from the correct // We can only guarantee that a function is called from the correct
@ -4052,6 +4073,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
const auto *FnType = const auto *FnType =
cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType()); cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType());
CGCallee Callee = OrigCallee;
if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function) && if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function) &&
(!TargetDecl || !isa<FunctionDecl>(TargetDecl))) { (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
if (llvm::Constant *PrefixSig = if (llvm::Constant *PrefixSig =
@ -4066,8 +4089,10 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
llvm::StructType *PrefixStructTy = llvm::StructType::get( llvm::StructType *PrefixStructTy = llvm::StructType::get(
CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true); CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true);
llvm::Value *CalleePtr = Callee.getFunctionPointer();
llvm::Value *CalleePrefixStruct = Builder.CreateBitCast( llvm::Value *CalleePrefixStruct = Builder.CreateBitCast(
Callee, llvm::PointerType::getUnqual(PrefixStructTy)); CalleePtr, llvm::PointerType::getUnqual(PrefixStructTy));
llvm::Value *CalleeSigPtr = llvm::Value *CalleeSigPtr =
Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 0); Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 0);
llvm::Value *CalleeSig = llvm::Value *CalleeSig =
@ -4090,7 +4115,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
EmitCheckTypeDescriptor(CalleeType) EmitCheckTypeDescriptor(CalleeType)
}; };
EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function), EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function),
"function_type_mismatch", StaticData, Callee); "function_type_mismatch", StaticData, CalleePtr);
Builder.CreateBr(Cont); Builder.CreateBr(Cont);
EmitBlock(Cont); EmitBlock(Cont);
@ -4107,7 +4132,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0)); llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0));
llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD); llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
llvm::Value *CastedCallee = Builder.CreateBitCast(Callee, Int8PtrTy); llvm::Value *CalleePtr = Callee.getFunctionPointer();
llvm::Value *CastedCallee = Builder.CreateBitCast(CalleePtr, Int8PtrTy);
llvm::Value *TypeTest = Builder.CreateCall( llvm::Value *TypeTest = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedCallee, TypeId}); CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedCallee, TypeId});
@ -4187,11 +4213,13 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
if (isa<FunctionNoProtoType>(FnType) || Chain) { if (isa<FunctionNoProtoType>(FnType) || Chain) {
llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo); llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo);
CalleeTy = CalleeTy->getPointerTo(); CalleeTy = CalleeTy->getPointerTo();
Callee = Builder.CreateBitCast(Callee, CalleeTy, "callee.knr.cast");
llvm::Value *CalleePtr = Callee.getFunctionPointer();
CalleePtr = Builder.CreateBitCast(CalleePtr, CalleeTy, "callee.knr.cast");
Callee.setFunctionPointer(CalleePtr);
} }
return EmitCall(FnInfo, Callee, ReturnValue, Args, return EmitCall(FnInfo, Callee, ReturnValue, Args);
CGCalleeInfo(NonCanonicalFTP, TargetDecl));
} }
LValue CodeGenFunction:: LValue CodeGenFunction::

View File

@ -80,26 +80,78 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
} }
RValue CodeGenFunction::EmitCXXMemberOrOperatorCall( RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue, const CXXMethodDecl *MD, const CGCallee &Callee,
ReturnValueSlot ReturnValue,
llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy,
const CallExpr *CE, CallArgList *RtlArgs) { const CallExpr *CE, CallArgList *RtlArgs) {
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
CallArgList Args; CallArgList Args;
RequiredArgs required = commonEmitCXXMemberOrOperatorCall( RequiredArgs required = commonEmitCXXMemberOrOperatorCall(
*this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs); *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);
return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required), auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required);
Callee, ReturnValue, Args, MD); return EmitCall(FnInfo, Callee, ReturnValue, Args);
} }
RValue CodeGenFunction::EmitCXXDestructorCall( RValue CodeGenFunction::EmitCXXDestructorCall(
const CXXDestructorDecl *DD, llvm::Value *Callee, llvm::Value *This, const CXXDestructorDecl *DD, const CGCallee &Callee, llvm::Value *This,
llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE,
StructorType Type) { StructorType Type) {
CallArgList Args; CallArgList Args;
commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam, commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam,
ImplicitParamTy, CE, Args, nullptr); ImplicitParamTy, CE, Args, nullptr);
return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(DD, Type), return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(DD, Type),
Callee, ReturnValueSlot(), Args, DD); Callee, ReturnValueSlot(), Args);
}
RValue CodeGenFunction::EmitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *E) {
QualType DestroyedType = E->getDestroyedType();
if (DestroyedType.hasStrongOrWeakObjCLifetime()) {
// Automatic Reference Counting:
// If the pseudo-expression names a retainable object with weak or
// strong lifetime, the object shall be released.
Expr *BaseExpr = E->getBase();
Address BaseValue = Address::invalid();
Qualifiers BaseQuals;
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
if (E->isArrow()) {
BaseValue = EmitPointerWithAlignment(BaseExpr);
const PointerType *PTy = BaseExpr->getType()->getAs<PointerType>();
BaseQuals = PTy->getPointeeType().getQualifiers();
} else {
LValue BaseLV = EmitLValue(BaseExpr);
BaseValue = BaseLV.getAddress();
QualType BaseTy = BaseExpr->getType();
BaseQuals = BaseTy.getQualifiers();
}
switch (DestroyedType.getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
break;
case Qualifiers::OCL_Strong:
EmitARCRelease(Builder.CreateLoad(BaseValue,
DestroyedType.isVolatileQualified()),
ARCPreciseLifetime);
break;
case Qualifiers::OCL_Weak:
EmitARCDestroyWeak(BaseValue);
break;
}
} else {
// C++ [expr.pseudo]p1:
// The result shall only be used as the operand for the function call
// operator (), and the result of such a call has type void. The only
// effect is the evaluation of the postfix-expression before the dot or
// arrow.
EmitIgnoredExpr(E->getBase());
}
return RValue::get(nullptr);
} }
static CXXRecordDecl *getCXXRecord(const Expr *E) { static CXXRecordDecl *getCXXRecord(const Expr *E) {
@ -124,8 +176,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
if (MD->isStatic()) { if (MD->isStatic()) {
// The method is static, emit it as we would a regular call. // The method is static, emit it as we would a regular call.
llvm::Value *Callee = CGM.GetAddrOfFunction(MD); CGCallee callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD), MD);
return EmitCall(getContext().getPointerType(MD->getType()), Callee, CE, return EmitCall(getContext().getPointerType(MD->getType()), callee, CE,
ReturnValue); ReturnValue);
} }
@ -251,8 +303,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
// We also don't emit a virtual call if the base expression has a record type // We also don't emit a virtual call if the base expression has a record type
// because then we know what the type is. // because then we know what the type is.
bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod; bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod;
llvm::Value *Callee;
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) { if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
assert(CE->arg_begin() == CE->arg_end() && assert(CE->arg_begin() == CE->arg_end() &&
"Destructor shouldn't have explicit parameters"); "Destructor shouldn't have explicit parameters");
@ -261,15 +312,19 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
CGM.getCXXABI().EmitVirtualDestructorCall( CGM.getCXXABI().EmitVirtualDestructorCall(
*this, Dtor, Dtor_Complete, This, cast<CXXMemberCallExpr>(CE)); *this, Dtor, Dtor_Complete, This, cast<CXXMemberCallExpr>(CE));
} else { } else {
CGCallee Callee;
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier) if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty); Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty);
else if (!DevirtualizedMethod) else if (!DevirtualizedMethod)
Callee = Callee = CGCallee::forDirect(
CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty); CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty),
Dtor);
else { else {
const CXXDestructorDecl *DDtor = const CXXDestructorDecl *DDtor =
cast<CXXDestructorDecl>(DevirtualizedMethod); cast<CXXDestructorDecl>(DevirtualizedMethod);
Callee = CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty); Callee = CGCallee::forDirect(
CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty),
DDtor);
} }
EmitCXXMemberOrOperatorCall( EmitCXXMemberOrOperatorCall(
CalleeDecl, Callee, ReturnValue, This.getPointer(), CalleeDecl, Callee, ReturnValue, This.getPointer(),
@ -278,8 +333,11 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
return RValue::get(nullptr); return RValue::get(nullptr);
} }
CGCallee Callee;
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty); Callee = CGCallee::forDirect(
CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty),
Ctor);
} else if (UseVirtualCall) { } else if (UseVirtualCall) {
Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty, Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty,
CE->getLocStart()); CE->getLocStart());
@ -294,9 +352,11 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier) if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty); Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty);
else if (!DevirtualizedMethod) else if (!DevirtualizedMethod)
Callee = CGM.GetAddrOfFunction(MD, Ty); Callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD, Ty), MD);
else { else {
Callee = CGM.GetAddrOfFunction(DevirtualizedMethod, Ty); Callee = CGCallee::forDirect(
CGM.GetAddrOfFunction(DevirtualizedMethod, Ty),
DevirtualizedMethod);
} }
} }
@ -341,7 +401,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
// Ask the ABI to load the callee. Note that This is modified. // Ask the ABI to load the callee. Note that This is modified.
llvm::Value *ThisPtrForCall = nullptr; llvm::Value *ThisPtrForCall = nullptr;
llvm::Value *Callee = CGCallee Callee =
CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This, CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This,
ThisPtrForCall, MemFnPtr, MPT); ThisPtrForCall, MemFnPtr, MPT);
@ -1173,23 +1233,24 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
/// Emit a call to an operator new or operator delete function, as implicitly /// Emit a call to an operator new or operator delete function, as implicitly
/// created by new-expressions and delete-expressions. /// created by new-expressions and delete-expressions.
static RValue EmitNewDeleteCall(CodeGenFunction &CGF, static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
const FunctionDecl *Callee, const FunctionDecl *CalleeDecl,
const FunctionProtoType *CalleeType, const FunctionProtoType *CalleeType,
const CallArgList &Args) { const CallArgList &Args) {
llvm::Instruction *CallOrInvoke; llvm::Instruction *CallOrInvoke;
llvm::Value *CalleeAddr = CGF.CGM.GetAddrOfFunction(Callee); llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl);
CGCallee Callee = CGCallee::forDirect(CalleePtr, CalleeDecl);
RValue RV = RValue RV =
CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall( CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
Args, CalleeType, /*chainCall=*/false), Args, CalleeType, /*chainCall=*/false),
CalleeAddr, ReturnValueSlot(), Args, Callee, &CallOrInvoke); Callee, ReturnValueSlot(), Args, &CallOrInvoke);
/// C++1y [expr.new]p10: /// C++1y [expr.new]p10:
/// [In a new-expression,] an implementation is allowed to omit a call /// [In a new-expression,] an implementation is allowed to omit a call
/// to a replaceable global allocation function. /// to a replaceable global allocation function.
/// ///
/// We model such elidable calls with the 'builtin' attribute. /// We model such elidable calls with the 'builtin' attribute.
llvm::Function *Fn = dyn_cast<llvm::Function>(CalleeAddr); llvm::Function *Fn = dyn_cast<llvm::Function>(CalleePtr);
if (Callee->isReplaceableGlobalAllocationFunction() && if (CalleeDecl->isReplaceableGlobalAllocationFunction() &&
Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) { Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
// FIXME: Add addAttribute to CallSite. // FIXME: Add addAttribute to CallSite.
if (llvm::CallInst *CI = dyn_cast<llvm::CallInst>(CallOrInvoke)) if (llvm::CallInst *CI = dyn_cast<llvm::CallInst>(CallOrInvoke))

View File

@ -598,10 +598,10 @@ ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(FuncInfo); llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(FuncInfo);
llvm::Constant *Func = CGF.CGM.CreateBuiltinFunction(FTy, LibCallName); llvm::Constant *Func = CGF.CGM.CreateBuiltinFunction(FTy, LibCallName);
llvm::Instruction *Call; CGCallee Callee = CGCallee::forDirect(Func, FQTy->getAs<FunctionProtoType>());
RValue Res = CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args, llvm::Instruction *Call;
FQTy->getAs<FunctionProtoType>(), &Call); RValue Res = CGF.EmitCall(FuncInfo, Callee, ReturnValueSlot(), Args, &Call);
cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getBuiltinCC()); cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getBuiltinCC());
return Res.getComplexVal(); return Res.getComplexVal();
} }

View File

@ -589,9 +589,10 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
args.add(RValue::get(CGF.Builder.getInt1(isAtomic)), Context.BoolTy); args.add(RValue::get(CGF.Builder.getInt1(isAtomic)), Context.BoolTy);
args.add(RValue::get(CGF.Builder.getInt1(hasStrong)), Context.BoolTy); args.add(RValue::get(CGF.Builder.getInt1(hasStrong)), Context.BoolTy);
llvm::Value *fn = CGF.CGM.getObjCRuntime().GetGetStructFunction(); llvm::Constant *fn = CGF.CGM.getObjCRuntime().GetGetStructFunction();
CGCallee callee = CGCallee::forDirect(fn);
CGF.EmitCall(CGF.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, args), CGF.EmitCall(CGF.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, args),
fn, ReturnValueSlot(), args); callee, ReturnValueSlot(), args);
} }
/// Determine whether the given architecture supports unaligned atomic /// Determine whether the given architecture supports unaligned atomic
@ -852,11 +853,12 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
// Third argument is the helper function. // Third argument is the helper function.
args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy);
llvm::Value *copyCppAtomicObjectFn = llvm::Constant *copyCppAtomicObjectFn =
CGF.CGM.getObjCRuntime().GetCppAtomicObjectGetFunction(); CGF.CGM.getObjCRuntime().GetCppAtomicObjectGetFunction();
CGCallee callee = CGCallee::forDirect(copyCppAtomicObjectFn);
CGF.EmitCall( CGF.EmitCall(
CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args),
copyCppAtomicObjectFn, ReturnValueSlot(), args); callee, ReturnValueSlot(), args);
} }
void void
@ -927,12 +929,13 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
} }
case PropertyImplStrategy::GetSetProperty: { case PropertyImplStrategy::GetSetProperty: {
llvm::Value *getPropertyFn = llvm::Constant *getPropertyFn =
CGM.getObjCRuntime().GetPropertyGetFunction(); CGM.getObjCRuntime().GetPropertyGetFunction();
if (!getPropertyFn) { if (!getPropertyFn) {
CGM.ErrorUnsupported(propImpl, "Obj-C getter requiring atomic copy"); CGM.ErrorUnsupported(propImpl, "Obj-C getter requiring atomic copy");
return; return;
} }
CGCallee callee = CGCallee::forDirect(getPropertyFn);
// Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true). // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
// FIXME: Can't this be simpler? This might even be worse than the // FIXME: Can't this be simpler? This might even be worse than the
@ -955,8 +958,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
llvm::Instruction *CallInstruction; llvm::Instruction *CallInstruction;
RValue RV = EmitCall( RValue RV = EmitCall(
getTypes().arrangeBuiltinFunctionCall(propType, args), getTypes().arrangeBuiltinFunctionCall(propType, args),
getPropertyFn, ReturnValueSlot(), args, CGCalleeInfo(), callee, ReturnValueSlot(), args, &CallInstruction);
&CallInstruction);
if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(CallInstruction)) if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(CallInstruction))
call->setTailCall(); call->setTailCall();
@ -1068,10 +1070,11 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
// FIXME: should this really always be false? // FIXME: should this really always be false?
args.add(RValue::get(CGF.Builder.getFalse()), CGF.getContext().BoolTy); args.add(RValue::get(CGF.Builder.getFalse()), CGF.getContext().BoolTy);
llvm::Value *copyStructFn = CGF.CGM.getObjCRuntime().GetSetStructFunction(); llvm::Constant *fn = CGF.CGM.getObjCRuntime().GetSetStructFunction();
CGCallee callee = CGCallee::forDirect(fn);
CGF.EmitCall( CGF.EmitCall(
CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args),
copyStructFn, ReturnValueSlot(), args); callee, ReturnValueSlot(), args);
} }
/// emitCPPObjectAtomicSetterCall - Call the runtime function to store /// emitCPPObjectAtomicSetterCall - Call the runtime function to store
@ -1103,11 +1106,12 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
// Third argument is the helper function. // Third argument is the helper function.
args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy);
llvm::Value *copyCppAtomicObjectFn = llvm::Constant *fn =
CGF.CGM.getObjCRuntime().GetCppAtomicObjectSetFunction(); CGF.CGM.getObjCRuntime().GetCppAtomicObjectSetFunction();
CGCallee callee = CGCallee::forDirect(fn);
CGF.EmitCall( CGF.EmitCall(
CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args),
copyCppAtomicObjectFn, ReturnValueSlot(), args); callee, ReturnValueSlot(), args);
} }
@ -1197,8 +1201,8 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
case PropertyImplStrategy::GetSetProperty: case PropertyImplStrategy::GetSetProperty:
case PropertyImplStrategy::SetPropertyAndExpressionGet: { case PropertyImplStrategy::SetPropertyAndExpressionGet: {
llvm::Value *setOptimizedPropertyFn = nullptr; llvm::Constant *setOptimizedPropertyFn = nullptr;
llvm::Value *setPropertyFn = nullptr; llvm::Constant *setPropertyFn = nullptr;
if (UseOptimizedSetter(CGM)) { if (UseOptimizedSetter(CGM)) {
// 10.8 and iOS 6.0 code and GC is off // 10.8 and iOS 6.0 code and GC is off
setOptimizedPropertyFn = setOptimizedPropertyFn =
@ -1236,8 +1240,9 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
if (setOptimizedPropertyFn) { if (setOptimizedPropertyFn) {
args.add(RValue::get(arg), getContext().getObjCIdType()); args.add(RValue::get(arg), getContext().getObjCIdType());
args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); args.add(RValue::get(ivarOffset), getContext().getPointerDiffType());
CGCallee callee = CGCallee::forDirect(setOptimizedPropertyFn);
EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args), EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args),
setOptimizedPropertyFn, ReturnValueSlot(), args); callee, ReturnValueSlot(), args);
} else { } else {
args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); args.add(RValue::get(ivarOffset), getContext().getPointerDiffType());
args.add(RValue::get(arg), getContext().getObjCIdType()); args.add(RValue::get(arg), getContext().getObjCIdType());
@ -1247,8 +1252,9 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
getContext().BoolTy); getContext().BoolTy);
// FIXME: We shouldn't need to get the function info here, the runtime // FIXME: We shouldn't need to get the function info here, the runtime
// already should have computed it to build the function. // already should have computed it to build the function.
CGCallee callee = CGCallee::forDirect(setPropertyFn);
EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args), EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args),
setPropertyFn, ReturnValueSlot(), args); callee, ReturnValueSlot(), args);
} }
return; return;
@ -1450,13 +1456,14 @@ QualType CodeGenFunction::TypeOfSelfObject() {
} }
void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
llvm::Constant *EnumerationMutationFn = llvm::Constant *EnumerationMutationFnPtr =
CGM.getObjCRuntime().EnumerationMutationFunction(); CGM.getObjCRuntime().EnumerationMutationFunction();
if (!EnumerationMutationFnPtr) {
if (!EnumerationMutationFn) {
CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime");
return; return;
} }
CGCallee EnumerationMutationFn =
CGCallee::forDirect(EnumerationMutationFnPtr);
CGDebugInfo *DI = getDebugInfo(); CGDebugInfo *DI = getDebugInfo();
if (DI) if (DI)

View File

@ -1386,9 +1386,10 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
llvm::Type::getInt1Ty(VMContext), IsClassMessage))}; llvm::Type::getInt1Ty(VMContext), IsClassMessage))};
llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD); llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);
CGCallee callee(CGCalleeInfo(), imp);
llvm::Instruction *call; llvm::Instruction *call;
RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
CGCalleeInfo(), &call);
call->setMetadata(msgSendMDKind, node); call->setMetadata(msgSendMDKind, node);
return msgRet; return msgRet;
} }
@ -1500,8 +1501,8 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
imp = EnforceType(Builder, imp, MSI.MessengerType); imp = EnforceType(Builder, imp, MSI.MessengerType);
llvm::Instruction *call; llvm::Instruction *call;
RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, CGCallee callee(CGCalleeInfo(), imp);
CGCalleeInfo(), &call); RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
call->setMetadata(msgSendMDKind, node); call->setMetadata(msgSendMDKind, node);

View File

@ -1978,8 +1978,9 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
llvm::Instruction *CallSite; llvm::Instruction *CallSite;
Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType); Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs, CGCallee Callee = CGCallee::forDirect(Fn);
CGCalleeInfo(), &CallSite); RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
&CallSite);
// Mark the call as noreturn if the method is marked noreturn and the // Mark the call as noreturn if the method is marked noreturn and the
// receiver cannot be null. // receiver cannot be null.
@ -6986,9 +6987,10 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
// Load the function to call from the message ref table. // Load the function to call from the message ref table.
Address calleeAddr = Address calleeAddr =
CGF.Builder.CreateStructGEP(mref, 0, CharUnits::Zero()); CGF.Builder.CreateStructGEP(mref, 0, CharUnits::Zero());
llvm::Value *callee = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn"); llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType); calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
CGCallee callee(CGCalleeInfo(), calleePtr);
RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args); RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
return nullReturn.complete(CGF, result, resultType, formalArgs, return nullReturn.complete(CGF, result, resultType, formalArgs,

View File

@ -248,7 +248,7 @@ void CodeGenFunction::FinishThunk() {
FinishFunction(); FinishFunction();
} }
void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee, void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr,
const ThunkInfo *Thunk) { const ThunkInfo *Thunk) {
assert(isa<CXXMethodDecl>(CurGD.getDecl()) && assert(isa<CXXMethodDecl>(CurGD.getDecl()) &&
"Please use a new CGF for this thunk"); "Please use a new CGF for this thunk");
@ -268,7 +268,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
CGM.ErrorUnsupported( CGM.ErrorUnsupported(
MD, "non-trivial argument copy for return-adjusting thunk"); MD, "non-trivial argument copy for return-adjusting thunk");
} }
EmitMustTailThunk(MD, AdjustedThisPtr, Callee); EmitMustTailThunk(MD, AdjustedThisPtr, CalleePtr);
return; return;
} }
@ -317,7 +317,8 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
// Now emit our call. // Now emit our call.
llvm::Instruction *CallOrInvoke; llvm::Instruction *CallOrInvoke;
RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, MD, &CallOrInvoke); CGCallee Callee = CGCallee::forDirect(CalleePtr, MD);
RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, &CallOrInvoke);
// Consider return adjustment if we have ThunkInfo. // Consider return adjustment if we have ThunkInfo.
if (Thunk && !Thunk->Return.isEmpty()) if (Thunk && !Thunk->Return.isEmpty())
@ -337,7 +338,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD, void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
llvm::Value *AdjustedThisPtr, llvm::Value *AdjustedThisPtr,
llvm::Value *Callee) { llvm::Value *CalleePtr) {
// Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery // Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery
// to translate AST arguments into LLVM IR arguments. For thunks, we know // to translate AST arguments into LLVM IR arguments. For thunks, we know
// that the caller prototype more or less matches the callee prototype with // that the caller prototype more or less matches the callee prototype with
@ -366,13 +367,14 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
// Emit the musttail call manually. Even if the prologue pushed cleanups, we // Emit the musttail call manually. Even if the prologue pushed cleanups, we
// don't actually want to run them. // don't actually want to run them.
llvm::CallInst *Call = Builder.CreateCall(Callee, Args); llvm::CallInst *Call = Builder.CreateCall(CalleePtr, Args);
Call->setTailCallKind(llvm::CallInst::TCK_MustTail); Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
// Apply the standard set of call attributes. // Apply the standard set of call attributes.
unsigned CallingConv; unsigned CallingConv;
CodeGen::AttributeListType AttributeList; CodeGen::AttributeListType AttributeList;
CGM.ConstructAttributeList(Callee->getName(), *CurFnInfo, MD, AttributeList, CGM.ConstructAttributeList(CalleePtr->getName(),
*CurFnInfo, MD, AttributeList,
CallingConv, /*AttrOnCallSite=*/true); CallingConv, /*AttrOnCallSite=*/true);
llvm::AttributeSet Attrs = llvm::AttributeSet Attrs =
llvm::AttributeSet::get(getLLVMContext(), AttributeList); llvm::AttributeSet::get(getLLVMContext(), AttributeList);
@ -398,7 +400,7 @@ void CodeGenFunction::generateThunk(llvm::Function *Fn,
// Get our callee. // Get our callee.
llvm::Type *Ty = llvm::Type *Ty =
CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeGlobalDeclaration(GD)); CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeGlobalDeclaration(GD));
llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
// Make the call and return the result. // Make the call and return the result.
EmitCallAndReturnForThunk(Callee, &Thunk); EmitCallAndReturnForThunk(Callee, &Thunk);

View File

@ -78,6 +78,7 @@ class ObjCAutoreleasePoolStmt;
namespace CodeGen { namespace CodeGen {
class CodeGenTypes; class CodeGenTypes;
class CGCallee;
class CGFunctionInfo; class CGFunctionInfo;
class CGRecordLayout; class CGRecordLayout;
class CGBlockInfo; class CGBlockInfo;
@ -1434,7 +1435,8 @@ public:
void StartThunk(llvm::Function *Fn, GlobalDecl GD, void StartThunk(llvm::Function *Fn, GlobalDecl GD,
const CGFunctionInfo &FnInfo); const CGFunctionInfo &FnInfo);
void EmitCallAndReturnForThunk(llvm::Value *Callee, const ThunkInfo *Thunk); void EmitCallAndReturnForThunk(llvm::Constant *Callee,
const ThunkInfo *Thunk);
void FinishThunk(); void FinishThunk();
@ -2842,17 +2844,17 @@ public:
/// EmitCall - Generate a call of the given function, expecting the given /// EmitCall - Generate a call of the given function, expecting the given
/// result type, and using the given argument list which specifies both the /// result type, and using the given argument list which specifies both the
/// LLVM arguments and the types they were derived from. /// LLVM arguments and the types they were derived from.
RValue EmitCall(const CGFunctionInfo &FnInfo, llvm::Value *Callee, RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee,
ReturnValueSlot ReturnValue, const CallArgList &Args, ReturnValueSlot ReturnValue, const CallArgList &Args,
CGCalleeInfo CalleeInfo = CGCalleeInfo(),
llvm::Instruction **callOrInvoke = nullptr); llvm::Instruction **callOrInvoke = nullptr);
RValue EmitCall(QualType FnType, llvm::Value *Callee, const CallExpr *E, RValue EmitCall(QualType FnType, const CGCallee &Callee, const CallExpr *E,
ReturnValueSlot ReturnValue, ReturnValueSlot ReturnValue,
CGCalleeInfo CalleeInfo = CGCalleeInfo(),
llvm::Value *Chain = nullptr); llvm::Value *Chain = nullptr);
RValue EmitCallExpr(const CallExpr *E, RValue EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue = ReturnValueSlot()); ReturnValueSlot ReturnValue = ReturnValueSlot());
RValue EmitSimpleCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue);
CGCallee EmitCallee(const Expr *E);
void checkTargetFeatures(const CallExpr *E, const FunctionDecl *TargetDecl); void checkTargetFeatures(const CallExpr *E, const FunctionDecl *TargetDecl);
@ -2878,21 +2880,23 @@ public:
void EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee, void EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
ArrayRef<llvm::Value*> args); ArrayRef<llvm::Value*> args);
llvm::Value *BuildAppleKextVirtualCall(const CXXMethodDecl *MD, CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
NestedNameSpecifier *Qual, NestedNameSpecifier *Qual,
llvm::Type *Ty); llvm::Type *Ty);
llvm::Value *BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD,
CXXDtorType Type, CXXDtorType Type,
const CXXRecordDecl *RD); const CXXRecordDecl *RD);
RValue RValue
EmitCXXMemberOrOperatorCall(const CXXMethodDecl *MD, llvm::Value *Callee, EmitCXXMemberOrOperatorCall(const CXXMethodDecl *Method,
const CGCallee &Callee,
ReturnValueSlot ReturnValue, llvm::Value *This, ReturnValueSlot ReturnValue, llvm::Value *This,
llvm::Value *ImplicitParam, llvm::Value *ImplicitParam,
QualType ImplicitParamTy, const CallExpr *E, QualType ImplicitParamTy, const CallExpr *E,
CallArgList *RtlArgs); CallArgList *RtlArgs);
RValue EmitCXXDestructorCall(const CXXDestructorDecl *DD, llvm::Value *Callee, RValue EmitCXXDestructorCall(const CXXDestructorDecl *DD,
const CGCallee &Callee,
llvm::Value *This, llvm::Value *ImplicitParam, llvm::Value *This, llvm::Value *ImplicitParam,
QualType ImplicitParamTy, const CallExpr *E, QualType ImplicitParamTy, const CallExpr *E,
StructorType Type); StructorType Type);
@ -2915,6 +2919,7 @@ public:
RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
const CXXMethodDecl *MD, const CXXMethodDecl *MD,
ReturnValueSlot ReturnValue); ReturnValueSlot ReturnValue);
RValue EmitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E);
RValue EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E, RValue EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E,
ReturnValueSlot ReturnValue); ReturnValueSlot ReturnValue);

View File

@ -832,8 +832,8 @@ public:
/// Given a builtin id for a function like "__builtin_fabsf", return a /// Given a builtin id for a function like "__builtin_fabsf", return a
/// Function* for "fabsf". /// Function* for "fabsf".
llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD, llvm::Constant *getBuiltinLibFunction(const FunctionDecl *FD,
unsigned BuiltinID); unsigned BuiltinID);
llvm::Function *getIntrinsic(unsigned IID, ArrayRef<llvm::Type*> Tys = None); llvm::Function *getIntrinsic(unsigned IID, ArrayRef<llvm::Type*> Tys = None);

View File

@ -114,7 +114,7 @@ public:
llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override; llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
llvm::Value * CGCallee
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
const Expr *E, const Expr *E,
Address This, Address This,
@ -263,9 +263,9 @@ public:
llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
CharUnits VPtrOffset) override; CharUnits VPtrOffset) override;
llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
Address This, llvm::Type *Ty, Address This, llvm::Type *Ty,
SourceLocation Loc) override; SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor, const CXXDestructorDecl *Dtor,
@ -520,7 +520,7 @@ ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
/// ///
/// If the member is non-virtual, memptr.ptr is the address of /// If the member is non-virtual, memptr.ptr is the address of
/// the function to call. /// the function to call.
llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
CodeGenFunction &CGF, const Expr *E, Address ThisAddr, CodeGenFunction &CGF, const Expr *E, Address ThisAddr,
llvm::Value *&ThisPtrForCall, llvm::Value *&ThisPtrForCall,
llvm::Value *MemFnPtr, const MemberPointerType *MPT) { llvm::Value *MemFnPtr, const MemberPointerType *MPT) {
@ -609,9 +609,11 @@ llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
// We're done. // We're done.
CGF.EmitBlock(FnEnd); CGF.EmitBlock(FnEnd);
llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo(), 2); llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2);
Callee->addIncoming(VirtualFn, FnVirtual); CalleePtr->addIncoming(VirtualFn, FnVirtual);
Callee->addIncoming(NonVirtualFn, FnNonVirtual); CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
CGCallee Callee(FPT, CalleePtr);
return Callee; return Callee;
} }
@ -1448,12 +1450,14 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating); llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
llvm::Value *Callee = nullptr; CGCallee Callee;
if (getContext().getLangOpts().AppleKext) if (getContext().getLangOpts().AppleKext &&
Type != Dtor_Base && DD->isVirtual())
Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent()); Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent());
else
if (!Callee) Callee =
Callee = CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)); CGCallee::forDirect(CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)),
DD);
CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(), CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(),
This.getPointer(), VTT, VTTTy, This.getPointer(), VTT, VTTTy,
@ -1598,19 +1602,20 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
return VTable; return VTable;
} }
llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD, GlobalDecl GD,
Address This, Address This,
llvm::Type *Ty, llvm::Type *Ty,
SourceLocation Loc) { SourceLocation Loc) {
GD = GD.getCanonicalDecl(); GD = GD.getCanonicalDecl();
Ty = Ty->getPointerTo()->getPointerTo(); Ty = Ty->getPointerTo()->getPointerTo();
auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl()); auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent()); llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent());
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD); uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
llvm::Value *VFunc;
if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) {
return CGF.EmitVTableTypeCheckedLoad( VFunc = CGF.EmitVTableTypeCheckedLoad(
MethodDecl->getParent(), VTable, MethodDecl->getParent(), VTable,
VTableIndex * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8); VTableIndex * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8);
} else { } else {
@ -1618,8 +1623,11 @@ llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
llvm::Value *VFuncPtr = llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
return CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); VFunc = CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
} }
CGCallee Callee(MethodDecl, VFunc);
return Callee;
} }
llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
@ -1631,7 +1639,7 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration( const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, getFromDtorType(DtorType)); Dtor, getFromDtorType(DtorType));
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
llvm::Value *Callee = CGCallee Callee =
getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty, getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty,
CE ? CE->getLocStart() : SourceLocation()); CE ? CE->getLocStart() : SourceLocation());

View File

@ -284,9 +284,9 @@ public:
llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
CharUnits VPtrOffset) override; CharUnits VPtrOffset) override;
llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
Address This, llvm::Type *Ty, Address This, llvm::Type *Ty,
SourceLocation Loc) override; SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor, const CXXDestructorDecl *Dtor,
@ -660,7 +660,7 @@ public:
CastKind CK, CastExpr::path_const_iterator PathBegin, CastKind CK, CastExpr::path_const_iterator PathBegin,
CastExpr::path_const_iterator PathEnd, llvm::Constant *Src); CastExpr::path_const_iterator PathEnd, llvm::Constant *Src);
llvm::Value * CGCallee
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E,
Address This, llvm::Value *&ThisPtrForCall, Address This, llvm::Value *&ThisPtrForCall,
llvm::Value *MemPtr, llvm::Value *MemPtr,
@ -1494,7 +1494,9 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *DD, const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase, CXXDtorType Type, bool ForVirtualBase,
bool Delegating, Address This) { bool Delegating, Address This) {
llvm::Value *Callee = CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)); CGCallee Callee = CGCallee::forDirect(
CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)),
DD);
if (DD->isVirtual()) { if (DD->isVirtual()) {
assert(Type != CXXDtorType::Dtor_Deleting && assert(Type != CXXDtorType::Dtor_Deleting &&
@ -1796,11 +1798,11 @@ getClassAtVTableLocation(ASTContext &Ctx, GlobalDecl GD,
return getClassAtVTableLocation(Ctx, RD, ML.VFPtrOffset); return getClassAtVTableLocation(Ctx, RD, ML.VFPtrOffset);
} }
llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD, GlobalDecl GD,
Address This, Address This,
llvm::Type *Ty, llvm::Type *Ty,
SourceLocation Loc) { SourceLocation Loc) {
GD = GD.getCanonicalDecl(); GD = GD.getCanonicalDecl();
CGBuilderTy &Builder = CGF.Builder; CGBuilderTy &Builder = CGF.Builder;
@ -1814,8 +1816,9 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
MicrosoftVTableContext::MethodVFTableLocation ML = MicrosoftVTableContext::MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD); CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
llvm::Value *VFunc;
if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) {
return CGF.EmitVTableTypeCheckedLoad( VFunc = CGF.EmitVTableTypeCheckedLoad(
getClassAtVTableLocation(getContext(), GD, ML), VTable, getClassAtVTableLocation(getContext(), GD, ML), VTable,
ML.Index * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8); ML.Index * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8);
} else { } else {
@ -1825,8 +1828,11 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
llvm::Value *VFuncPtr = llvm::Value *VFuncPtr =
Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
return Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign()); VFunc = Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
} }
CGCallee Callee(MethodDecl, VFunc);
return Callee;
} }
llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
@ -1841,7 +1847,7 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration( const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, StructorType::Deleting); Dtor, StructorType::Deleting);
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
llvm::Value *Callee = getVirtualFunctionPointer( CGCallee Callee = getVirtualFunctionPointer(
CGF, GD, This, Ty, CE ? CE->getLocStart() : SourceLocation()); CGF, GD, This, Ty, CE ? CE->getLocStart() : SourceLocation());
ASTContext &Context = getContext(); ASTContext &Context = getContext();
@ -3231,7 +3237,7 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
return Dst; return Dst;
} }
llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
CodeGenFunction &CGF, const Expr *E, Address This, CodeGenFunction &CGF, const Expr *E, Address This,
llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
const MemberPointerType *MPT) { const MemberPointerType *MPT) {
@ -3278,7 +3284,10 @@ llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
"this.adjusted"); "this.adjusted");
} }
return Builder.CreateBitCast(FunctionPointer, FTy->getPointerTo()); FunctionPointer =
Builder.CreateBitCast(FunctionPointer, FTy->getPointerTo());
CGCallee Callee(FPT, FunctionPointer);
return Callee;
} }
CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) { CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
@ -3892,10 +3901,12 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
/*Delegating=*/false, Args); /*Delegating=*/false, Args);
// Call the destructor with our arguments. // Call the destructor with our arguments.
llvm::Value *CalleeFn = CGM.getAddrOfCXXStructor(CD, StructorType::Complete); llvm::Constant *CalleePtr =
CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
CGCallee Callee = CGCallee::forDirect(CalleePtr, CD);
const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall( const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall(
Args, CD, Ctor_Complete, ExtraArgs); Args, CD, Ctor_Complete, ExtraArgs);
CGF.EmitCall(CalleeInfo, CalleeFn, ReturnValueSlot(), Args, CD); CGF.EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args);
Cleanups.ForceCleanup(); Cleanups.ForceCleanup();