diff options
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 45 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 43 |
3 files changed, 72 insertions, 20 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 54a3e59378..da3cd3ca10 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -176,8 +176,8 @@ void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { return; } - EmitCXXConstructor(D, Ctor_Complete); - EmitCXXConstructor(D, Ctor_Base); + EmitGlobal(GlobalDecl(D, Ctor_Complete)); + EmitGlobal(GlobalDecl(D, Ctor_Base)); } void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 976621847f..48e1a1e2ec 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -135,6 +135,17 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, } } +const char *CodeGenModule::getMangledName(const GlobalDecl &GD) { + const NamedDecl *ND = GD.getDecl(); + + if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND)) + return getMangledCXXCtorName(D, GD.getCtorType()); + if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND)) + return getMangledCXXDtorName(D, GD.getDtorType()); + + return getMangledName(ND); +} + /// \brief Retrieves the mangled name for the given declaration. /// /// If the given declaration requires a mangled name, returns an @@ -411,7 +422,7 @@ void CodeGenModule::EmitDeferred() { // previously unused static decl may become used during the generation of code // for a static function, iterate until no changes are made. while (!DeferredDeclsToEmit.empty()) { - const ValueDecl *D = DeferredDeclsToEmit.back(); + GlobalDecl D = DeferredDeclsToEmit.back(); DeferredDeclsToEmit.pop_back(); // The mangled name for the decl must have been emitted in GlobalDeclMap. @@ -502,7 +513,9 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { return VD->getStorageClass() == VarDecl::Static; } -void CodeGenModule::EmitGlobal(const ValueDecl *Global) { +void CodeGenModule::EmitGlobal(const GlobalDecl &GD) { + const ValueDecl *Global = GD.getDecl(); + // If this is an alias definition (which otherwise looks like a declaration) // emit it now. if (Global->hasAttr<AliasAttr>()) @@ -532,28 +545,32 @@ void CodeGenModule::EmitGlobal(const ValueDecl *Global) { if (MayDeferGeneration(Global)) { // If the value has already been used, add it directly to the // DeferredDeclsToEmit list. - const char *MangledName = getMangledName(Global); + const char *MangledName = getMangledName(GD); if (GlobalDeclMap.count(MangledName)) - DeferredDeclsToEmit.push_back(Global); + DeferredDeclsToEmit.push_back(GD); else { // Otherwise, remember that we saw a deferred decl with this name. The // first use of the mangled name will cause it to move into // DeferredDeclsToEmit. - DeferredDecls[MangledName] = Global; + DeferredDecls[MangledName] = GD; } return; } // Otherwise emit the definition. - EmitGlobalDefinition(Global); + EmitGlobalDefinition(GD); } -void CodeGenModule::EmitGlobalDefinition(const ValueDecl *D) { - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { +void CodeGenModule::EmitGlobalDefinition(const 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 (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) EmitGlobalVarDefinition(VD); - } else { + else { assert(0 && "Invalid argument to EmitGlobalDefinition()"); } } @@ -582,7 +599,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, // 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::DenseMap<const char*, const ValueDecl*>::iterator DDI = + llvm::DenseMap<const char*, GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName); if (DDI != DeferredDecls.end()) { // Move the potentially referenced deferred decl to the DeferredDeclsToEmit @@ -654,7 +671,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName, // 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::DenseMap<const char*, const ValueDecl*>::iterator DDI = + llvm::DenseMap<const char*, GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName); if (DDI != DeferredDecls.end()) { // Move the potentially referenced deferred decl to the DeferredDeclsToEmit @@ -725,7 +742,7 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { // later. const char *MangledName = getMangledName(D); if (GlobalDeclMap.count(MangledName) == 0) { - DeferredDecls[MangledName] = D; + DeferredDecls[MangledName] = GlobalDecl(D); return; } } @@ -1356,7 +1373,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::CXXMethod: case Decl::Function: case Decl::Var: - EmitGlobal(cast<ValueDecl>(D)); + EmitGlobal(GlobalDecl(cast<ValueDecl>(D))); break; // C++ Decls diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 21ef8da863..3db311243c 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -16,6 +16,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/AST/Attr.h" +#include "clang/AST/DeclCXX.h" #include "CGBlocks.h" #include "CGCall.h" #include "CGCXX.h" @@ -108,16 +109,48 @@ 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 /// not been referenced yet. The key to this map is a uniqued mangled name. - llvm::DenseMap<const char*, const ValueDecl*> DeferredDecls; + llvm::DenseMap<const char*, GlobalDecl> DeferredDecls; /// DeferredDeclsToEmit - This is a list of deferred decls which we have seen /// that *are* actually referenced. These get code generated when the module /// is done. - std::vector<const ValueDecl*> DeferredDeclsToEmit; + std::vector<GlobalDecl> DeferredDeclsToEmit; /// LLVMUsed - List of global values which are required to be /// present in the object file; bitcast to i8*. This is used for @@ -326,6 +359,8 @@ public: const Decl *TargetDecl, AttributeListType &PAL); + const char *getMangledName(const GlobalDecl &D); + const char *getMangledName(const NamedDecl *ND); const char *getMangledCXXCtorName(const CXXConstructorDecl *D, CXXCtorType Type); @@ -371,9 +406,9 @@ private: /// EmitGlobal - Emit code for a singal global function or var decl. Forward /// declarations are emitted lazily. - void EmitGlobal(const ValueDecl *D); + void EmitGlobal(const GlobalDecl& D); - void EmitGlobalDefinition(const ValueDecl *D); + void EmitGlobalDefinition(const GlobalDecl& D); void EmitGlobalFunctionDefinition(const FunctionDecl *D); void EmitGlobalVarDefinition(const VarDecl *D); |