forked from OSchip/llvm-project
Avoid adding some decls to DeferredDeclsToEmit.
Before this patch GetOrCreateLLVMFunction would add a decl to DeferredDeclsToEmit even when it was being called by the function trying to emit that decl. llvm-svn: 196753
This commit is contained in:
parent
048f90cc04
commit
94abb8ffed
|
@ -205,8 +205,8 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
|
|||
const CGFunctionInfo &fnInfo =
|
||||
getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
|
||||
|
||||
llvm::Function *fn =
|
||||
cast<llvm::Function>(GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo));
|
||||
llvm::Function *fn = cast<llvm::Function>(
|
||||
GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo, true));
|
||||
setFunctionLinkage(GlobalDecl(ctor, ctorType), fn);
|
||||
|
||||
CodeGenFunction(*this).GenerateCode(GlobalDecl(ctor, ctorType), fn, fnInfo);
|
||||
|
@ -218,7 +218,8 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
|
|||
llvm::GlobalValue *
|
||||
CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor,
|
||||
CXXCtorType ctorType,
|
||||
const CGFunctionInfo *fnInfo) {
|
||||
const CGFunctionInfo *fnInfo,
|
||||
bool DontDefer) {
|
||||
GlobalDecl GD(ctor, ctorType);
|
||||
|
||||
StringRef name = getMangledName(GD);
|
||||
|
@ -230,7 +231,8 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor,
|
|||
|
||||
llvm::FunctionType *fnType = getTypes().GetFunctionType(*fnInfo);
|
||||
return cast<llvm::Function>(GetOrCreateLLVMFunction(name, fnType, GD,
|
||||
/*ForVTable=*/false));
|
||||
/*ForVTable=*/false,
|
||||
DontDefer));
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
|
||||
|
@ -260,8 +262,8 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
|
|||
const CGFunctionInfo &fnInfo =
|
||||
getTypes().arrangeCXXDestructor(dtor, dtorType);
|
||||
|
||||
llvm::Function *fn =
|
||||
cast<llvm::Function>(GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo));
|
||||
llvm::Function *fn = cast<llvm::Function>(
|
||||
GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo, 0, true));
|
||||
setFunctionLinkage(GlobalDecl(dtor, dtorType), fn);
|
||||
|
||||
CodeGenFunction(*this).GenerateCode(GlobalDecl(dtor, dtorType), fn, fnInfo);
|
||||
|
@ -274,7 +276,8 @@ llvm::GlobalValue *
|
|||
CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor,
|
||||
CXXDtorType dtorType,
|
||||
const CGFunctionInfo *fnInfo,
|
||||
llvm::FunctionType *fnType) {
|
||||
llvm::FunctionType *fnType,
|
||||
bool DontDefer) {
|
||||
GlobalDecl GD(dtor, dtorType);
|
||||
|
||||
StringRef name = getMangledName(GD);
|
||||
|
@ -286,7 +289,8 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor,
|
|||
fnType = getTypes().GetFunctionType(*fnInfo);
|
||||
}
|
||||
return cast<llvm::Function>(GetOrCreateLLVMFunction(name, fnType, GD,
|
||||
/*ForVTable=*/false));
|
||||
/*ForVTable=*/false,
|
||||
DontDefer));
|
||||
}
|
||||
|
||||
static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
|
||||
|
|
|
@ -54,7 +54,8 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
|
|||
Out.flush();
|
||||
|
||||
llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD);
|
||||
return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true);
|
||||
return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true,
|
||||
/*DontDefer*/ true);
|
||||
}
|
||||
|
||||
static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
|
||||
|
|
|
@ -1374,6 +1374,7 @@ llvm::Constant *
|
|||
CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
|
||||
llvm::Type *Ty,
|
||||
GlobalDecl GD, bool ForVTable,
|
||||
bool DontDefer,
|
||||
llvm::AttributeSet ExtraAttrs) {
|
||||
const Decl *D = GD.getDecl();
|
||||
|
||||
|
@ -1393,14 +1394,6 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
|
|||
return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo());
|
||||
}
|
||||
|
||||
// All MSVC dtors other than the base dtor are linkonce_odr and delegate to
|
||||
// each other bottoming out with the base dtor. Therefore we emit non-base
|
||||
// dtors on usage, even if there is no dtor definition in the TU.
|
||||
if (D && isa<CXXDestructorDecl>(D) &&
|
||||
getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
|
||||
GD.getDtorType()))
|
||||
DeferredDeclsToEmit.push_back(GD);
|
||||
|
||||
// This function doesn't have a complete type (for example, the return
|
||||
// type is an incomplete struct). Use a fake type instead, and make
|
||||
// sure not to try to set attributes.
|
||||
|
@ -1428,50 +1421,64 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
|
|||
B));
|
||||
}
|
||||
|
||||
// This is the first use or definition of a mangled name. If there is a
|
||||
// deferred decl with this name, remember that we need to emit it at the end
|
||||
// of the file.
|
||||
llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
|
||||
if (DDI != DeferredDecls.end()) {
|
||||
// Move the potentially referenced deferred decl to the DeferredDeclsToEmit
|
||||
// list, and remove it from DeferredDecls (since we don't need it anymore).
|
||||
DeferredDeclsToEmit.push_back(DDI->second);
|
||||
DeferredDecls.erase(DDI);
|
||||
if (!DontDefer) {
|
||||
// All MSVC dtors other than the base dtor are linkonce_odr and delegate to
|
||||
// each other bottoming out with the base dtor. Therefore we emit non-base
|
||||
// dtors on usage, even if there is no dtor definition in the TU.
|
||||
if (D && isa<CXXDestructorDecl>(D) &&
|
||||
getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
|
||||
GD.getDtorType()))
|
||||
DeferredDeclsToEmit.push_back(GD);
|
||||
|
||||
// Otherwise, if this is a sized deallocation function, emit a weak definition
|
||||
// for it at the end of the translation unit.
|
||||
} else if (D && cast<FunctionDecl>(D)
|
||||
->getCorrespondingUnsizedGlobalDeallocationFunction()) {
|
||||
DeferredDeclsToEmit.push_back(GD);
|
||||
// This is the first use or definition of a mangled name. If there is a
|
||||
// deferred decl with this name, remember that we need to emit it at the end
|
||||
// of the file.
|
||||
llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
|
||||
if (DDI != DeferredDecls.end()) {
|
||||
// Move the potentially referenced deferred decl to the
|
||||
// DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
|
||||
// don't need it anymore).
|
||||
DeferredDeclsToEmit.push_back(DDI->second);
|
||||
DeferredDecls.erase(DDI);
|
||||
|
||||
// Otherwise, there are cases we have to worry about where we're
|
||||
// using a declaration for which we must emit a definition but where
|
||||
// we might not find a top-level definition:
|
||||
// - member functions defined inline in their classes
|
||||
// - friend functions defined inline in some class
|
||||
// - special member functions with implicit definitions
|
||||
// If we ever change our AST traversal to walk into class methods,
|
||||
// this will be unnecessary.
|
||||
//
|
||||
// We also don't emit a definition for a function if it's going to be an entry
|
||||
// in a vtable, unless it's already marked as used.
|
||||
} else if (getLangOpts().CPlusPlus && D) {
|
||||
// Look for a declaration that's lexically in a record.
|
||||
const FunctionDecl *FD = cast<FunctionDecl>(D);
|
||||
FD = FD->getMostRecentDecl();
|
||||
do {
|
||||
if (isa<CXXRecordDecl>(FD->getLexicalDeclContext())) {
|
||||
if (FD->isImplicit() && !ForVTable) {
|
||||
assert(FD->isUsed() && "Sema didn't mark implicit function as used!");
|
||||
DeferredDeclsToEmit.push_back(GD.getWithDecl(FD));
|
||||
break;
|
||||
} else if (FD->doesThisDeclarationHaveABody()) {
|
||||
DeferredDeclsToEmit.push_back(GD.getWithDecl(FD));
|
||||
break;
|
||||
// Otherwise, if this is a sized deallocation function, emit a weak
|
||||
// definition
|
||||
// for it at the end of the translation unit.
|
||||
} else if (D && cast<FunctionDecl>(D)
|
||||
->getCorrespondingUnsizedGlobalDeallocationFunction()) {
|
||||
DeferredDeclsToEmit.push_back(GD);
|
||||
|
||||
// Otherwise, there are cases we have to worry about where we're
|
||||
// using a declaration for which we must emit a definition but where
|
||||
// we might not find a top-level definition:
|
||||
// - member functions defined inline in their classes
|
||||
// - friend functions defined inline in some class
|
||||
// - special member functions with implicit definitions
|
||||
// If we ever change our AST traversal to walk into class methods,
|
||||
// this will be unnecessary.
|
||||
//
|
||||
// We also don't emit a definition for a function if it's going to be an
|
||||
// entry
|
||||
// in a vtable, unless it's already marked as used.
|
||||
} else if (getLangOpts().CPlusPlus && D) {
|
||||
// Look for a declaration that's lexically in a record.
|
||||
const FunctionDecl *FD = cast<FunctionDecl>(D);
|
||||
FD = FD->getMostRecentDecl();
|
||||
do {
|
||||
if (isa<CXXRecordDecl>(FD->getLexicalDeclContext())) {
|
||||
if (FD->isImplicit() && !ForVTable) {
|
||||
assert(FD->isUsed() &&
|
||||
"Sema didn't mark implicit function as used!");
|
||||
DeferredDeclsToEmit.push_back(GD.getWithDecl(FD));
|
||||
break;
|
||||
} else if (FD->doesThisDeclarationHaveABody()) {
|
||||
DeferredDeclsToEmit.push_back(GD.getWithDecl(FD));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
FD = FD->getPreviousDecl();
|
||||
} while (FD);
|
||||
FD = FD->getPreviousDecl();
|
||||
} while (FD);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the result is of the requested type.
|
||||
|
@ -1489,13 +1496,14 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
|
|||
/// create it (this occurs when we see a definition of the function).
|
||||
llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
|
||||
llvm::Type *Ty,
|
||||
bool ForVTable) {
|
||||
bool ForVTable,
|
||||
bool DontDefer) {
|
||||
// If there was no specific requested type, just convert it now.
|
||||
if (!Ty)
|
||||
Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType());
|
||||
|
||||
StringRef MangledName = getMangledName(GD);
|
||||
return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable);
|
||||
return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer);
|
||||
}
|
||||
|
||||
/// CreateRuntimeFunction - Create a new runtime function with the specified
|
||||
|
@ -1504,9 +1512,9 @@ llvm::Constant *
|
|||
CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy,
|
||||
StringRef Name,
|
||||
llvm::AttributeSet ExtraAttrs) {
|
||||
llvm::Constant *C
|
||||
= GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
|
||||
ExtraAttrs);
|
||||
llvm::Constant *C =
|
||||
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
|
||||
/*DontDefer=*/false, ExtraAttrs);
|
||||
if (llvm::Function *F = dyn_cast<llvm::Function>(C))
|
||||
if (F->empty())
|
||||
F->setCallingConv(getRuntimeCC());
|
||||
|
@ -2090,7 +2098,8 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
|
|||
llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
|
||||
|
||||
// Get or create the prototype for the function.
|
||||
llvm::Constant *Entry = GetAddrOfFunction(GD, Ty);
|
||||
llvm::Constant *Entry =
|
||||
GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer*/ true);
|
||||
|
||||
// Strip off a bitcast if we got one back.
|
||||
if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
|
||||
|
|
|
@ -639,9 +639,9 @@ public:
|
|||
/// GetAddrOfFunction - Return the address of the given function. If Ty is
|
||||
/// non-null, then this function will use the specified type if it has to
|
||||
/// create it.
|
||||
llvm::Constant *GetAddrOfFunction(GlobalDecl GD,
|
||||
llvm::Type *Ty = 0,
|
||||
bool ForVTable = false);
|
||||
llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = 0,
|
||||
bool ForVTable = false,
|
||||
bool DontDefer = false);
|
||||
|
||||
/// GetAddrOfRTTIDescriptor - Get the address of the RTTI descriptor
|
||||
/// for the given type.
|
||||
|
@ -769,14 +769,16 @@ public:
|
|||
/// given type.
|
||||
llvm::GlobalValue *GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor,
|
||||
CXXCtorType ctorType,
|
||||
const CGFunctionInfo *fnInfo = 0);
|
||||
const CGFunctionInfo *fnInfo = 0,
|
||||
bool DontDefer = false);
|
||||
|
||||
/// GetAddrOfCXXDestructor - Return the address of the constructor of the
|
||||
/// given type.
|
||||
llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor,
|
||||
CXXDtorType dtorType,
|
||||
const CGFunctionInfo *fnInfo = 0,
|
||||
llvm::FunctionType *fnType = 0);
|
||||
llvm::FunctionType *fnType = 0,
|
||||
bool DontDefer = false);
|
||||
|
||||
/// getBuiltinLibFunction - Given a builtin id for a function like
|
||||
/// "__builtin_fabsf", return a Function* for "fabsf".
|
||||
|
@ -1009,12 +1011,11 @@ public:
|
|||
private:
|
||||
llvm::GlobalValue *GetGlobalValue(StringRef Ref);
|
||||
|
||||
llvm::Constant *GetOrCreateLLVMFunction(StringRef MangledName,
|
||||
llvm::Type *Ty,
|
||||
GlobalDecl D,
|
||||
bool ForVTable,
|
||||
llvm::AttributeSet ExtraAttrs =
|
||||
llvm::AttributeSet());
|
||||
llvm::Constant *
|
||||
GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D,
|
||||
bool ForVTable, bool DontDefer = false,
|
||||
llvm::AttributeSet ExtraAttrs = llvm::AttributeSet());
|
||||
|
||||
llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName,
|
||||
llvm::PointerType *PTy,
|
||||
const VarDecl *D,
|
||||
|
|
Loading…
Reference in New Issue