forked from OSchip/llvm-project
push GlobalDecl through enough of the CodeGenModule interfaces
to allow us to support generation of deferred ctors/dtors. It looks like codegen isn't emitting a call to the dtor in member-functions.cpp:test2, but when it does, its body should get emitted. llvm-svn: 71594
This commit is contained in:
parent
d035ebda2f
commit
e0be0dfced
|
@ -109,7 +109,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {
|
|||
const llvm::Type *Ty =
|
||||
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
|
||||
FPT->isVariadic());
|
||||
llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, Ty);
|
||||
llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty);
|
||||
|
||||
llvm::Value *This;
|
||||
|
||||
|
@ -204,8 +204,8 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
|
|||
getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false);
|
||||
|
||||
const char *Name = getMangledCXXCtorName(D, Type);
|
||||
|
||||
return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, D));
|
||||
return cast<llvm::Function>(
|
||||
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
|
||||
}
|
||||
|
||||
const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D,
|
||||
|
@ -245,7 +245,8 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
|
|||
getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false);
|
||||
|
||||
const char *Name = getMangledCXXDtorName(D, Type);
|
||||
return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, D));
|
||||
return cast<llvm::Function>(
|
||||
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
|
||||
}
|
||||
|
||||
const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D,
|
||||
|
|
|
@ -400,7 +400,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
|
||||
const FunctionDecl *FD = CA->getFunctionDecl();
|
||||
|
||||
llvm::Constant* F = CGM.GetAddrOfFunction(FD);
|
||||
llvm::Constant* F = CGM.GetAddrOfFunction(GlobalDecl(FD));
|
||||
assert(F && "Could not find function!");
|
||||
|
||||
CleanupScope scope(*this);
|
||||
|
|
|
@ -673,7 +673,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
|||
LV.SetGlobalObjCRef(LV, true);
|
||||
return LV;
|
||||
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
|
||||
return LValue::MakeAddr(CGM.GetAddrOfFunction(FD),
|
||||
return LValue::MakeAddr(CGM.GetAddrOfFunction(GlobalDecl(FD)),
|
||||
E->getType().getCVRQualifiers(),
|
||||
getContext().getObjCGCAttrKind(E->getType()));
|
||||
}
|
||||
|
|
|
@ -406,7 +406,7 @@ public:
|
|||
case Expr::QualifiedDeclRefExprClass: {
|
||||
NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
|
||||
return CGM.GetAddrOfFunction(FD);
|
||||
return CGM.GetAddrOfFunction(GlobalDecl(FD));
|
||||
if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
|
||||
// We can never refer to a variable with local storage.
|
||||
if (!VD->hasLocalStorage()) {
|
||||
|
|
|
@ -513,7 +513,7 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
|
|||
return VD->getStorageClass() == VarDecl::Static;
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitGlobal(const GlobalDecl &GD) {
|
||||
void CodeGenModule::EmitGlobal(GlobalDecl GD) {
|
||||
const ValueDecl *Global = GD.getDecl();
|
||||
|
||||
// If this is an alias definition (which otherwise looks like a declaration)
|
||||
|
@ -561,13 +561,13 @@ void CodeGenModule::EmitGlobal(const GlobalDecl &GD) {
|
|||
EmitGlobalDefinition(GD);
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitGlobalDefinition(const GlobalDecl &GD) {
|
||||
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
|
||||
const ValueDecl *D = GD.getDecl();
|
||||
|
||||
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
|
||||
EmitCXXConstructor(CD, GD.getCtorType());
|
||||
else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
||||
EmitGlobalFunctionDefinition(FD);
|
||||
else if (isa<FunctionDecl>(D))
|
||||
EmitGlobalFunctionDefinition(GD);
|
||||
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
|
||||
EmitGlobalVarDefinition(VD);
|
||||
else {
|
||||
|
@ -584,7 +584,7 @@ void CodeGenModule::EmitGlobalDefinition(const GlobalDecl &GD) {
|
|||
/// to set the attributes on the function when it is first created.
|
||||
llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
|
||||
const llvm::Type *Ty,
|
||||
const FunctionDecl *D) {
|
||||
GlobalDecl D) {
|
||||
// Lookup the entry, lazily creating it if necessary.
|
||||
llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
|
||||
if (Entry) {
|
||||
|
@ -606,15 +606,12 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
|
|||
// list, and remove it from DeferredDecls (since we don't need it anymore).
|
||||
DeferredDeclsToEmit.push_back(DDI->second);
|
||||
DeferredDecls.erase(DDI);
|
||||
} else if (D && D->isThisDeclarationADefinition() && MayDeferGeneration(D)) {
|
||||
} else if (const FunctionDecl *FD = cast_or_null<FunctionDecl>(D.getDecl())) {
|
||||
// If this the first reference to a C++ inline function in a class, queue up
|
||||
// the deferred function body for emission. These are not seen as
|
||||
// top-level declarations.
|
||||
// FIXME: Make this work for ctor/dtors. We need to pass down a full
|
||||
// GlobalDecl instead of just a FunctionDecl.
|
||||
if (!isa<CXXConstructorDecl>(D) &&
|
||||
!isa<CXXDestructorDecl>(D))
|
||||
DeferredDeclsToEmit.push_back(GlobalDecl(D));
|
||||
if (FD->isThisDeclarationADefinition() && MayDeferGeneration(FD))
|
||||
DeferredDeclsToEmit.push_back(D);
|
||||
}
|
||||
|
||||
// This function doesn't have a complete type (for example, the return
|
||||
|
@ -630,8 +627,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
|
|||
llvm::Function::ExternalLinkage,
|
||||
"", &getModule());
|
||||
F->setName(MangledName);
|
||||
if (D && ShouldSetAttributes)
|
||||
SetFunctionAttributes(D, F);
|
||||
if (D.getDecl() && ShouldSetAttributes)
|
||||
SetFunctionAttributes(cast<FunctionDecl>(D.getDecl()), F);
|
||||
Entry = F;
|
||||
return F;
|
||||
}
|
||||
|
@ -639,12 +636,12 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
|
|||
/// 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 (this occurs when we see a definition of the function).
|
||||
llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D,
|
||||
llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
|
||||
const llvm::Type *Ty) {
|
||||
// If there was no specific requested type, just convert it now.
|
||||
if (!Ty)
|
||||
Ty = getTypes().ConvertType(D->getType());
|
||||
return GetOrCreateLLVMFunction(getMangledName(D), Ty, D);
|
||||
Ty = getTypes().ConvertType(GD.getDecl()->getType());
|
||||
return GetOrCreateLLVMFunction(getMangledName(GD.getDecl()), Ty, GD);
|
||||
}
|
||||
|
||||
/// CreateRuntimeFunction - Create a new runtime function with the specified
|
||||
|
@ -654,7 +651,7 @@ CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
|
|||
const char *Name) {
|
||||
// Convert Name to be a uniqued string from the IdentifierInfo table.
|
||||
Name = getContext().Idents.get(Name).getName();
|
||||
return GetOrCreateLLVMFunction(Name, FTy, 0);
|
||||
return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl());
|
||||
}
|
||||
|
||||
/// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module,
|
||||
|
@ -924,9 +921,10 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
|
|||
}
|
||||
|
||||
|
||||
void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
|
||||
void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
|
||||
const llvm::FunctionType *Ty;
|
||||
|
||||
const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
|
||||
|
||||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
|
||||
bool isVariadic = D->getType()->getAsFunctionProtoType()->isVariadic();
|
||||
|
||||
|
@ -948,7 +946,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
|
|||
}
|
||||
|
||||
// Get or create the prototype for the function.
|
||||
llvm::Constant *Entry = GetAddrOfFunction(D, Ty);
|
||||
llvm::Constant *Entry = GetAddrOfFunction(GD, Ty);
|
||||
|
||||
// Strip off a bitcast if we got one back.
|
||||
if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
|
||||
|
@ -973,7 +971,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
|
|||
// (e.g. "int f(int x)"). Start by making a new function of the
|
||||
// correct type, RAUW, then steal the name.
|
||||
GlobalDeclMap.erase(getMangledName(D));
|
||||
llvm::Function *NewFn = cast<llvm::Function>(GetAddrOfFunction(D, Ty));
|
||||
llvm::Function *NewFn = cast<llvm::Function>(GetAddrOfFunction(GD, Ty));
|
||||
NewFn->takeName(OldFn);
|
||||
|
||||
// If this is an implementation of a function without a prototype, try to
|
||||
|
@ -1024,7 +1022,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
|
|||
// if a deferred decl.
|
||||
llvm::Constant *Aliasee;
|
||||
if (isa<llvm::FunctionType>(DeclTy))
|
||||
Aliasee = GetOrCreateLLVMFunction(AliaseeName, DeclTy, 0);
|
||||
Aliasee = GetOrCreateLLVMFunction(AliaseeName, DeclTy, GlobalDecl());
|
||||
else
|
||||
Aliasee = GetOrCreateLLVMGlobal(AliaseeName,
|
||||
llvm::PointerType::getUnqual(DeclTy), 0);
|
||||
|
@ -1105,7 +1103,7 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(unsigned BuiltinID) {
|
|||
// Unique the name through the identifier table.
|
||||
Name = getContext().Idents.get(Name).getName();
|
||||
// FIXME: param attributes for sext/zext etc.
|
||||
return GetOrCreateLLVMFunction(Name, Ty, 0);
|
||||
return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
|
||||
}
|
||||
|
||||
llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys,
|
||||
|
|
|
@ -65,6 +65,38 @@ namespace CodeGen {
|
|||
class CGDebugInfo;
|
||||
class CGObjCRuntime;
|
||||
|
||||
/// GlobalDecl - represents a global declaration. This can either be a
|
||||
/// CXXConstructorDecl and the constructor type (Base, Complete).
|
||||
/// a CXXDestructorDecl and the destructor type (Base, Complete) or
|
||||
// a regular VarDecl or a FunctionDecl.
|
||||
class GlobalDecl {
|
||||
llvm::PointerIntPair<const ValueDecl*, 2> Value;
|
||||
|
||||
public:
|
||||
GlobalDecl() {}
|
||||
|
||||
explicit GlobalDecl(const ValueDecl *VD) : Value(VD, 0) {
|
||||
assert(!isa<CXXConstructorDecl>(VD) && "Use other ctor with ctor decls!");
|
||||
assert(!isa<CXXDestructorDecl>(VD) && "Use other ctor with dtor decls!");
|
||||
}
|
||||
GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
|
||||
: Value(D, Type) {}
|
||||
GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
|
||||
: Value(D, Type) {}
|
||||
|
||||
const ValueDecl *getDecl() const { return Value.getPointer(); }
|
||||
|
||||
CXXCtorType getCtorType() const {
|
||||
assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
|
||||
return static_cast<CXXCtorType>(Value.getInt());
|
||||
}
|
||||
|
||||
CXXDtorType getDtorType() const {
|
||||
assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
|
||||
return static_cast<CXXDtorType>(Value.getInt());
|
||||
}
|
||||
};
|
||||
|
||||
/// CodeGenModule - This class organizes the cross-function state that is used
|
||||
/// while generating LLVM code.
|
||||
class CodeGenModule : public BlockModule {
|
||||
|
@ -109,38 +141,6 @@ class CodeGenModule : public BlockModule {
|
|||
/// has one).
|
||||
llvm::StringSet<> MangledNames;
|
||||
|
||||
/// GlobalDecl - represents a global declaration. This can either be a
|
||||
/// CXXConstructorDecl and the constructor type (Base, Complete).
|
||||
/// a CXXDestructorDecl and the destructor type (Base, Complete) or
|
||||
// a regular VarDecl or a FunctionDecl.
|
||||
class GlobalDecl {
|
||||
llvm::PointerIntPair<const ValueDecl*, 2> Value;
|
||||
|
||||
public:
|
||||
GlobalDecl() {}
|
||||
|
||||
explicit GlobalDecl(const ValueDecl *VD) : Value(VD, 0) {
|
||||
assert(!isa<CXXConstructorDecl>(VD) && "Use other ctor with ctor decls!");
|
||||
assert(!isa<CXXDestructorDecl>(VD) && "Use other ctor with dtor decls!");
|
||||
}
|
||||
GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
|
||||
: Value(D, Type) {}
|
||||
GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
|
||||
: Value(D, Type) {}
|
||||
|
||||
const ValueDecl *getDecl() const { return Value.getPointer(); }
|
||||
|
||||
CXXCtorType getCtorType() const {
|
||||
assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
|
||||
return static_cast<CXXCtorType>(Value.getInt());
|
||||
}
|
||||
|
||||
CXXDtorType getDtorType() const {
|
||||
assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
|
||||
return static_cast<CXXDtorType>(Value.getInt());
|
||||
}
|
||||
};
|
||||
|
||||
/// DeferredDecls - This contains all the decls which have definitions but
|
||||
/// which are deferred for emission and therefore should only be output if
|
||||
/// they are actually used. If a decl is in this, then it is known to have
|
||||
|
@ -220,7 +220,7 @@ 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(const FunctionDecl *D,
|
||||
llvm::Constant *GetAddrOfFunction(GlobalDecl GD,
|
||||
const llvm::Type *Ty = 0);
|
||||
|
||||
/// GetStringForStringLiteral - Return the appropriate bytes for a string
|
||||
|
@ -383,7 +383,7 @@ private:
|
|||
|
||||
llvm::Constant *GetOrCreateLLVMFunction(const char *MangledName,
|
||||
const llvm::Type *Ty,
|
||||
const FunctionDecl *D);
|
||||
GlobalDecl D);
|
||||
llvm::Constant *GetOrCreateLLVMGlobal(const char *MangledName,
|
||||
const llvm::PointerType *PTy,
|
||||
const VarDecl *D);
|
||||
|
@ -406,11 +406,11 @@ private:
|
|||
|
||||
/// EmitGlobal - Emit code for a singal global function or var decl. Forward
|
||||
/// declarations are emitted lazily.
|
||||
void EmitGlobal(const GlobalDecl& D);
|
||||
void EmitGlobal(GlobalDecl D);
|
||||
|
||||
void EmitGlobalDefinition(const GlobalDecl& D);
|
||||
void EmitGlobalDefinition(GlobalDecl D);
|
||||
|
||||
void EmitGlobalFunctionDefinition(const FunctionDecl *D);
|
||||
void EmitGlobalFunctionDefinition(GlobalDecl GD);
|
||||
void EmitGlobalVarDefinition(const VarDecl *D);
|
||||
void EmitAliasDefinition(const ValueDecl *D);
|
||||
void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);
|
||||
|
@ -437,8 +437,8 @@ private:
|
|||
void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type);
|
||||
|
||||
// FIXME: Hardcoding priority here is gross.
|
||||
void AddGlobalCtor(llvm::Function * Ctor, int Priority=65535);
|
||||
void AddGlobalDtor(llvm::Function * Dtor, int Priority=65535);
|
||||
void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535);
|
||||
void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535);
|
||||
|
||||
/// EmitCtorList - Generates a global array of functions and priorities using
|
||||
/// the given list and name. This array will have appending linkage and is
|
||||
|
|
|
@ -20,8 +20,10 @@ void test1() {
|
|||
|
||||
|
||||
struct S {
|
||||
S() { }
|
||||
~S() { }
|
||||
// RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t &&
|
||||
inline S() { }
|
||||
// RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t &&
|
||||
inline ~S() { }
|
||||
|
||||
|
||||
void f_inline1() { }
|
||||
|
|
Loading…
Reference in New Issue