[opaque pointer types] Pass through function types for TLS

initialization and global destructor calls.

Differential Revision: https://reviews.llvm.org/D57801

llvm-svn: 353355
This commit is contained in:
James Y Knight 2019-02-07 01:14:17 +00:00
parent 18f0bd78e2
commit f7321540d5
8 changed files with 62 additions and 44 deletions

View File

@ -227,10 +227,11 @@ llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
return Fn;
}
llvm::Constant *CodeGenModule::getAddrOfCXXStructor(
llvm::FunctionCallee CodeGenModule::getAddrAndTypeOfCXXStructor(
const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo,
llvm::FunctionType *FnType, bool DontDefer,
ForDefinition_t IsForDefinition) {
GlobalDecl GD;
if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
GD = GlobalDecl(CD, toCXXCtorType(Type));
@ -249,9 +250,10 @@ llvm::Constant *CodeGenModule::getAddrOfCXXStructor(
FnType = getTypes().GetFunctionType(*FnInfo);
}
return GetOrCreateLLVMFunction(
llvm::Constant *Ptr = GetOrCreateLLVMFunction(
getMangledName(GD), FnType, GD, /*ForVTable=*/false, DontDefer,
/*isThunk=*/false, /*ExtraAttrs=*/llvm::AttributeList(), IsForDefinition);
return {FnType, Ptr};
}
static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,

View File

@ -556,7 +556,7 @@ public:
/// \param Dtor - a function taking a single pointer argument
/// \param Addr - a pointer to pass to the destructor function.
virtual void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
llvm::Constant *Dtor,
llvm::FunctionCallee Dtor,
llvm::Constant *Addr) = 0;
/*************************** thread_local initialization ********************/

View File

@ -97,7 +97,7 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
return;
}
llvm::Constant *Func;
llvm::FunctionCallee Func;
llvm::Constant *Argument;
// Special-case non-array C++ destructors, if they have the right signature.
@ -117,7 +117,7 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
assert(!Record->hasTrivialDestructor());
CXXDestructorDecl *Dtor = Record->getDestructor();
Func = CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete);
Func = CGM.getAddrAndTypeOfCXXStructor(Dtor, StructorType::Complete);
Argument = llvm::ConstantExpr::getBitCast(
Addr.getPointer(), CGF.getTypes().ConvertType(Type)->getPointerTo());
@ -214,8 +214,8 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
/// Create a stub function, suitable for being passed to atexit,
/// which passes the given address to the given destructor function.
llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD,
llvm::Constant *dtor,
llvm::Function *CodeGenFunction::createAtExitStub(const VarDecl &VD,
llvm::FunctionCallee dtor,
llvm::Constant *addr) {
// Get the destructor function type, void(*)(void).
llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false);
@ -238,7 +238,7 @@ llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD,
// Make sure the call and the callee agree on calling convention.
if (llvm::Function *dtorFn =
dyn_cast<llvm::Function>(dtor->stripPointerCasts()))
dyn_cast<llvm::Function>(dtor.getCallee()->stripPointerCasts()))
call->setCallingConv(dtorFn->getCallingConv());
CGF.FinishFunction();
@ -248,7 +248,7 @@ llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD,
/// Register a global destructor using the C atexit runtime function.
void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,
llvm::Constant *dtor,
llvm::FunctionCallee dtor,
llvm::Constant *addr) {
// Create a function which calls the destructor.
llvm::Constant *dtorStub = createAtExitStub(VD, dtor, addr);
@ -681,8 +681,8 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
void CodeGenFunction::GenerateCXXGlobalDtorsFunc(
llvm::Function *Fn,
const std::vector<std::pair<llvm::WeakTrackingVH, llvm::Constant *>>
&DtorsAndObjects) {
const std::vector<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,
llvm::Constant *>> &DtorsAndObjects) {
{
auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
@ -692,9 +692,11 @@ void CodeGenFunction::GenerateCXXGlobalDtorsFunc(
// Emit the dtors, in reverse order from construction.
for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
llvm::CallInst *CI = Builder.CreateCall(Callee,
DtorsAndObjects[e - i - 1].second);
llvm::FunctionType *CalleeTy;
llvm::Value *Callee;
llvm::Constant *Arg;
std::tie(CalleeTy, Callee, Arg) = DtorsAndObjects[e - i - 1];
llvm::CallInst *CI = Builder.CreateCall(CalleeTy, Callee, Arg);
// Make sure the call and the callee agree on calling convention.
if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
CI->setCallingConv(F->getCallingConv());

View File

@ -330,7 +330,7 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
switch (M->getStorageDuration()) {
case SD_Static:
case SD_Thread: {
llvm::Constant *CleanupFn;
llvm::FunctionCallee CleanupFn;
llvm::Constant *CleanupArg;
if (E->getType()->isArrayType()) {
CleanupFn = CodeGenFunction(CGF.CGM).generateDestroyHelper(
@ -339,7 +339,7 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
dyn_cast_or_null<VarDecl>(M->getExtendingDecl()));
CleanupArg = llvm::Constant::getNullValue(CGF.Int8PtrTy);
} else {
CleanupFn = CGF.CGM.getAddrOfCXXStructor(ReferenceTemporaryDtor,
CleanupFn = CGF.CGM.getAddrAndTypeOfCXXStructor(ReferenceTemporaryDtor,
StructorType::Complete);
CleanupArg = cast<llvm::Constant>(ReferenceTemporary.getPointer());
}

View File

@ -3924,12 +3924,12 @@ public:
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr,
bool PerformInit);
llvm::Constant *createAtExitStub(const VarDecl &VD, llvm::Constant *Dtor,
llvm::Function *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor,
llvm::Constant *Addr);
/// Call atexit() with a function that passes the given argument to
/// the given function.
void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::Constant *fn,
void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::FunctionCallee fn,
llvm::Constant *addr);
/// Call atexit() with function dtorStub.
@ -3962,8 +3962,8 @@ public:
/// variables.
void GenerateCXXGlobalDtorsFunc(
llvm::Function *Fn,
const std::vector<std::pair<llvm::WeakTrackingVH, llvm::Constant *>>
&DtorsAndObjects);
const std::vector<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,
llvm::Constant *>> &DtorsAndObjects);
void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
const VarDecl *D,

View File

@ -451,7 +451,9 @@ private:
SmallVector<GlobalInitData, 8> PrioritizedCXXGlobalInits;
/// Global destructor functions and arguments that need to run on termination.
std::vector<std::pair<llvm::WeakTrackingVH, llvm::Constant *>> CXXGlobalDtors;
std::vector<
std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH, llvm::Constant *>>
CXXGlobalDtors;
/// The complete set of modules that has been imported.
llvm::SetVector<clang::Module *> ImportedModules;
@ -958,6 +960,17 @@ public:
const CGFunctionInfo *FnInfo = nullptr,
llvm::FunctionType *FnType = nullptr,
bool DontDefer = false,
ForDefinition_t IsForDefinition = NotForDefinition) {
return cast<llvm::Constant>(getAddrAndTypeOfCXXStructor(MD, Type, FnInfo,
FnType, DontDefer,
IsForDefinition)
.getCallee());
}
llvm::FunctionCallee getAddrAndTypeOfCXXStructor(
const CXXMethodDecl *MD, StructorType Type,
const CGFunctionInfo *FnInfo = nullptr,
llvm::FunctionType *FnType = nullptr, bool DontDefer = false,
ForDefinition_t IsForDefinition = NotForDefinition);
/// Given a builtin id for a function like "__builtin_fabsf", return a
@ -998,8 +1011,9 @@ public:
void addCompilerUsedGlobal(llvm::GlobalValue *GV);
/// Add a destructor and object to add to the C++ global destructor function.
void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object) {
CXXGlobalDtors.emplace_back(DtorFn, Object);
void AddCXXDtorEntry(llvm::FunctionCallee DtorFn, llvm::Constant *Object) {
CXXGlobalDtors.emplace_back(DtorFn.getFunctionType(), DtorFn.getCallee(),
Object);
}
/// Create or return a runtime function declaration with the specified type

View File

@ -328,7 +328,8 @@ public:
llvm::GlobalVariable *DeclPtr,
bool PerformInit) override;
void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
llvm::Constant *dtor, llvm::Constant *addr) override;
llvm::FunctionCallee dtor,
llvm::Constant *addr) override;
llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD,
llvm::Value *Val);
@ -2284,9 +2285,8 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
/// Register a global destructor using __cxa_atexit.
static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
llvm::Constant *dtor,
llvm::Constant *addr,
bool TLS) {
llvm::FunctionCallee dtor,
llvm::Constant *addr, bool TLS) {
const char *Name = "__cxa_atexit";
if (TLS) {
const llvm::Triple &T = CGF.getTarget().getTriple();
@ -2322,11 +2322,10 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
// function.
addr = llvm::Constant::getNullValue(CGF.Int8PtrTy);
llvm::Value *args[] = {
llvm::ConstantExpr::getBitCast(dtor, dtorTy),
llvm::Value *args[] = {llvm::ConstantExpr::getBitCast(
cast<llvm::Constant>(dtor.getCallee()), dtorTy),
llvm::ConstantExpr::getBitCast(addr, CGF.Int8PtrTy),
handle
};
handle};
CGF.EmitNounwindRuntimeCall(atexit, args);
}
@ -2375,9 +2374,8 @@ void CodeGenModule::registerGlobalDtorsWithAtExit() {
}
/// Register a global destructor as best as we know how.
void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
llvm::Constant *dtor,
void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
llvm::FunctionCallee dtor,
llvm::Constant *addr) {
if (D.isNoDestroy(CGM.getContext()))
return;
@ -2541,6 +2539,8 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
}
llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.VoidTy, false);
// If we have a definition for the variable, emit the initialization
// function as an alias to the global Init function (if any). Otherwise,
// produce a declaration of the initialization function.
@ -2559,8 +2559,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
// This function will not exist if the TU defining the thread_local
// variable in question does not need any dynamic initialization for
// its thread_local variables.
llvm::FunctionType *FnTy = llvm::FunctionType::get(CGM.VoidTy, false);
Init = llvm::Function::Create(FnTy,
Init = llvm::Function::Create(InitFnTy,
llvm::GlobalVariable::ExternalWeakLinkage,
InitFnName.str(), &CGM.getModule());
const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
@ -2578,7 +2577,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
CGBuilderTy Builder(CGM, Entry);
if (InitIsInitFunc) {
if (Init) {
llvm::CallInst *CallVal = Builder.CreateCall(Init);
llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init);
if (isThreadWrapperReplaceable(VD, CGM)) {
CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
llvm::Function *Fn =
@ -2594,7 +2593,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
Builder.CreateCondBr(Have, InitBB, ExitBB);
Builder.SetInsertPoint(InitBB);
Builder.CreateCall(Init);
Builder.CreateCall(InitFnTy, Init);
Builder.CreateBr(ExitBB);
Builder.SetInsertPoint(ExitBB);

View File

@ -394,7 +394,8 @@ public:
llvm::GlobalVariable *DeclPtr,
bool PerformInit) override;
void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
llvm::Constant *Dtor, llvm::Constant *Addr) override;
llvm::FunctionCallee Dtor,
llvm::Constant *Addr) override;
// ==== Notes on array cookies =========
//
@ -2222,7 +2223,7 @@ Address MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
}
static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD,
llvm::Constant *Dtor,
llvm::FunctionCallee Dtor,
llvm::Constant *Addr) {
// Create a function which calls the destructor.
llvm::Constant *DtorStub = CGF.createAtExitStub(VD, Dtor, Addr);
@ -2241,7 +2242,7 @@ static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD,
}
void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
llvm::Constant *Dtor,
llvm::FunctionCallee Dtor,
llvm::Constant *Addr) {
if (D.isNoDestroy(CGM.getContext()))
return;