[cfe-commits] r96451 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/default-arguments.cpp test/CodeGenCXX/mangle-subst-std.cpp test/CodeGenCXX/mangle.cpp test/CodeGenCXX/member-templates.cpp test/CodeGenCXX/virtual-bases.cpp test/CodeGenCXX/virtual-destructor-calls.cpp test/CodeGenCXX/vtable-pointer-initialization.cpp

John McCall rjmccall at apple.com
Tue Feb 16 19:52:49 PST 2010


Author: rjmccall
Date: Tue Feb 16 21:52:49 2010
New Revision: 96451

URL: http://llvm.org/viewvc/llvm-project?rev=96451&view=rev
Log:
Emit complete constructors and destructors as aliases to base constructors
and destructors when the two entities are semantically identical, i.e. when
the class has no virtual base classes.  We only do this for linkage types
for which aliases are supported, i.e. internal and external, i.e. not linkonce.


Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/test/CodeGenCXX/default-arguments.cpp
    cfe/trunk/test/CodeGenCXX/mangle-subst-std.cpp
    cfe/trunk/test/CodeGenCXX/mangle.cpp
    cfe/trunk/test/CodeGenCXX/member-templates.cpp
    cfe/trunk/test/CodeGenCXX/virtual-bases.cpp
    cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp
    cfe/trunk/test/CodeGenCXX/vtable-pointer-initialization.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Tue Feb 16 21:52:49 2010
@@ -26,17 +26,88 @@
 using namespace clang;
 using namespace CodeGen;
 
+/// Try to emit a definition as a global alias for another definition.
+bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
+                                             GlobalDecl TargetDecl) {
+  // Find the referrent.
+  llvm::GlobalValue *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
+
+  // Look for an existing entry.
+  const char *MangledName = getMangledName(AliasDecl);
+  llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
+  if (Entry) {
+    assert(Entry->isDeclaration() && "definition already exists for alias");
+    assert(Entry->getType() == Ref->getType() &&
+           "declaration exists with different type");
+  }
+
+  // The alias will use the linkage of the referrent.  If we can't
+  // support aliases with that linkage, fail.
+  llvm::GlobalValue::LinkageTypes Linkage
+    = getFunctionLinkage(cast<FunctionDecl>(AliasDecl.getDecl()));
+
+  switch (Linkage) {
+  // We can definitely emit aliases to definitions with external linkage.
+  case llvm::GlobalValue::ExternalLinkage:
+  case llvm::GlobalValue::ExternalWeakLinkage:
+    break;
+
+  // Same with local linkage.
+  case llvm::GlobalValue::InternalLinkage:
+  case llvm::GlobalValue::PrivateLinkage:
+  case llvm::GlobalValue::LinkerPrivateLinkage:
+    break;
+
+  // We should try to support linkonce linkages.
+  case llvm::GlobalValue::LinkOnceAnyLinkage:
+  case llvm::GlobalValue::LinkOnceODRLinkage:
+    return true;
+
+  // Other linkages will probably never be supported.
+  default:
+    return true;
+  }
+
+  // Create the alias with no name.
+  llvm::GlobalAlias *Alias = 
+    new llvm::GlobalAlias(Ref->getType(), Linkage, "", Ref, &getModule());
+
+  // Switch any previous uses to the alias and continue.
+  if (Entry) {
+    Entry->replaceAllUsesWith(Alias);
+    Entry->eraseFromParent();
+  }
+  Entry = Alias;
+
+  // Finally, set up the alias with its proper name and attributes.
+  Alias->setName(MangledName);
+  SetCommonAttributes(AliasDecl.getDecl(), Alias);
+
+  return false;
+}
 
 
 void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
-  EmitGlobal(GlobalDecl(D, Ctor_Complete));
+  // The constructor used for constructing this as a base class;
+  // ignores virtual bases.
   EmitGlobal(GlobalDecl(D, Ctor_Base));
+
+  // The constructor used for constructing this as a complete class;
+  // constucts the virtual bases, then calls the base constructor.
+  EmitGlobal(GlobalDecl(D, Ctor_Complete));
 }
 
 void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
                                        CXXCtorType Type) {
+  // The complete constructor is equivalent to the base constructor
+  // for classes with no virtual bases.  Try to emit it as an alias.
+  if (Type == Ctor_Complete &&
+      !D->getParent()->getNumVBases() &&
+      !TryEmitDefinitionAsAlias(GlobalDecl(D, Ctor_Complete),
+                                GlobalDecl(D, Ctor_Base)))
+    return;
 
-  llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type);
+  llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXConstructor(D, Type));
 
   CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
 
@@ -44,15 +115,17 @@
   SetLLVMFunctionAttributesForDefinition(D, Fn);
 }
 
-llvm::Function *
+llvm::GlobalValue *
 CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
                                        CXXCtorType Type) {
+  const char *Name = getMangledCXXCtorName(D, Type);
+  if (llvm::GlobalValue *V = GlobalDeclMap[Name])
+    return V;
+
   const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
   const llvm::FunctionType *FTy =
     getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), 
                                FPT->isVariadic());
-
-  const char *Name = getMangledCXXCtorName(D, Type);
   return cast<llvm::Function>(
                       GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
 }
@@ -67,15 +140,32 @@
 }
 
 void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
+  // The destructor used for destructing this as a base class; ignores
+  // virtual bases.
+  EmitGlobal(GlobalDecl(D, Dtor_Base));
+
+  // The destructor used for destructing this as a most-derived class;
+  // call the base destructor and then destructs any virtual bases.
+  EmitGlobal(GlobalDecl(D, Dtor_Complete));
+
+  // The destructor in a virtual table is always a 'deleting'
+  // destructor, which calls the complete destructor and then uses the
+  // appropriate operator delete.
   if (D->isVirtual())
     EmitGlobal(GlobalDecl(D, Dtor_Deleting));
-  EmitGlobal(GlobalDecl(D, Dtor_Complete));
-  EmitGlobal(GlobalDecl(D, Dtor_Base));
 }
 
 void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
                                       CXXDtorType Type) {
-  llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type);
+  // The complete destructor is equivalent to the base destructor for
+  // classes with no virtual bases, so try to emit it as an alias.
+  if (Type == Dtor_Complete &&
+      !D->getParent()->getNumVBases() &&
+      !TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Complete),
+                                GlobalDecl(D, Dtor_Base)))
+    return;
+
+  llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXDestructor(D, Type));
 
   CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
 
@@ -83,13 +173,16 @@
   SetLLVMFunctionAttributesForDefinition(D, Fn);
 }
 
-llvm::Function *
+llvm::GlobalValue *
 CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
                                       CXXDtorType Type) {
+  const char *Name = getMangledCXXDtorName(D, Type);
+  if (llvm::GlobalValue *V = GlobalDeclMap[Name])
+    return V;
+
   const llvm::FunctionType *FTy =
     getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false);
 
-  const char *Name = getMangledCXXDtorName(D, Type);
   return cast<llvm::Function>(
                       GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
 }

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Feb 16 21:52:49 2010
@@ -316,24 +316,20 @@
   return CodeGenModule::GVA_CXXInline;
 }
 
-/// SetFunctionDefinitionAttributes - Set attributes for a global.
-///
-/// FIXME: This is currently only done for aliases and functions, but not for
-/// variables (these details are set in EmitGlobalVarDefinition for variables).
-void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
-                                                    llvm::GlobalValue *GV) {
+llvm::GlobalValue::LinkageTypes
+CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
   GVALinkage Linkage = GetLinkageForFunction(getContext(), D, Features);
 
   if (Linkage == GVA_Internal) {
-    GV->setLinkage(llvm::Function::InternalLinkage);
+    return llvm::Function::InternalLinkage;
   } else if (D->hasAttr<DLLExportAttr>()) {
-    GV->setLinkage(llvm::Function::DLLExportLinkage);
+    return llvm::Function::DLLExportLinkage;
   } else if (D->hasAttr<WeakAttr>()) {
-    GV->setLinkage(llvm::Function::WeakAnyLinkage);
+    return llvm::Function::WeakAnyLinkage;
   } else if (Linkage == GVA_C99Inline) {
     // In C99 mode, 'inline' functions are guaranteed to have a strong
     // definition somewhere else, so we can use available_externally linkage.
-    GV->setLinkage(llvm::Function::AvailableExternallyLinkage);
+    return llvm::Function::AvailableExternallyLinkage;
   } else if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) {
     // In C++, the compiler has to emit a definition in every translation unit
     // that references the function.  We should use linkonce_odr because
@@ -341,13 +337,22 @@
     // don't need to codegen it.  b) if the function persists, it needs to be
     // merged with other definitions. c) C++ has the ODR, so we know the
     // definition is dependable.
-    GV->setLinkage(llvm::Function::LinkOnceODRLinkage);
+    return llvm::Function::LinkOnceODRLinkage;
   } else {
     assert(Linkage == GVA_StrongExternal);
     // Otherwise, we have strong external linkage.
-    GV->setLinkage(llvm::Function::ExternalLinkage);
+    return llvm::Function::ExternalLinkage;
   }
+}
+
 
+/// SetFunctionDefinitionAttributes - Set attributes for a global.
+///
+/// FIXME: This is currently only done for aliases and functions, but not for
+/// variables (these details are set in EmitGlobalVarDefinition for variables).
+void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
+                                                    llvm::GlobalValue *GV) {
+  GV->setLinkage(getFunctionLinkage(D));
   SetCommonAttributes(D, GV);
 }
 

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Feb 16 21:52:49 2010
@@ -206,6 +206,19 @@
   /// GlobalValue.
   void setGlobalVisibility(llvm::GlobalValue *GV, const Decl *D) const;
 
+  llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) {
+    if (isa<CXXConstructorDecl>(GD.getDecl()))
+      return GetAddrOfCXXConstructor(cast<CXXConstructorDecl>(GD.getDecl()),
+                                     GD.getCtorType());
+    else if (isa<CXXDestructorDecl>(GD.getDecl()))
+      return GetAddrOfCXXDestructor(cast<CXXDestructorDecl>(GD.getDecl()),
+                                     GD.getDtorType());
+    else if (isa<FunctionDecl>(GD.getDecl()))
+      return GetAddrOfFunction(GD);
+    else
+      return GetAddrOfGlobalVar(cast<VarDecl>(GD.getDecl()));
+  }
+
   /// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
   /// given global variable.  If Ty is non-null and if the global doesn't exist,
   /// then it will be greated with the specified type instead of whatever the
@@ -291,13 +304,13 @@
 
   /// GetAddrOfCXXConstructor - Return the address of the constructor of the
   /// given type.
-  llvm::Function *GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
-                                          CXXCtorType Type);
+  llvm::GlobalValue *GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
+                                             CXXCtorType Type);
 
   /// GetAddrOfCXXDestructor - Return the address of the constructor of the
   /// given type.
-  llvm::Function *GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
-                                         CXXDtorType Type);
+  llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
+                                            CXXDtorType Type);
 
   /// getBuiltinLibFunction - Given a builtin id for a function like
   /// "__builtin_fabsf", return a Function* for "fabsf".
@@ -417,6 +430,9 @@
     GVA_TemplateInstantiation
   };
 
+  llvm::GlobalVariable::LinkageTypes
+  getFunctionLinkage(const FunctionDecl *FD);
+
   /// getVtableLinkage - Return the appropriate linkage for the vtable, VTT,
   /// and type information of the given class.
   static llvm::GlobalVariable::LinkageTypes 
@@ -468,6 +484,8 @@
 
   // C++ related functions.
 
+  bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
+
   void EmitNamespace(const NamespaceDecl *D);
   void EmitLinkageSpec(const LinkageSpecDecl *D);
 

Modified: cfe/trunk/test/CodeGenCXX/default-arguments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/default-arguments.cpp?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/default-arguments.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/default-arguments.cpp Tue Feb 16 21:52:49 2010
@@ -26,6 +26,8 @@
  B(const A1& = A1(), const A2& = A2());
 };
 
+// CHECK: @_ZN1CC1Ev = alias {{.*}} @_ZN1CC2Ev
+
 // CHECK: define void @_Z2f1v()
 void f1() {
 
@@ -42,13 +44,6 @@
  C();
 };
 
-// CHECK: define void @_ZN1CC1Ev(
-// CHECK: call void @_ZN2A1C1Ev(
-// CHECK: call void @_ZN2A2C1Ev(
-// CHECK: call void @_ZN1BC1ERK2A1RK2A2(
-// CHECK: call void @_ZN2A2D1Ev
-// CHECK: call void @_ZN2A1D1Ev
-
 // CHECK: define void @_ZN1CC2Ev(
 // CHECK: call void @_ZN2A1C1Ev(
 // CHECK: call void @_ZN2A2C1Ev(

Modified: cfe/trunk/test/CodeGenCXX/mangle-subst-std.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-subst-std.cpp?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-subst-std.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-subst-std.cpp Tue Feb 16 21:52:49 2010
@@ -1,9 +1,10 @@
 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
 
+// CHECK: @_ZNSt1AC1Ev = alias {{.*}} @_ZNSt1AC2Ev
+
 namespace std {
   struct A { A(); };
   
-  // CHECK: define void @_ZNSt1AC1Ev
   // CHECK: define void @_ZNSt1AC2Ev
   A::A() { }
 };

Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Tue Feb 16 21:52:49 2010
@@ -11,6 +11,8 @@
 //CHECK: @pr5966_i = external global
 //CHECK: @_ZL8pr5966_i = internal global
 
+// CHECK: @_ZN2S7C1Ev = alias {{.*}} @_ZN2S7C2Ev
+
 // CHECK: define zeroext i1 @_ZplRK1YRA100_P1X
 bool operator+(const Y&, X* (&xs)[100]) { return false; }
 
@@ -219,7 +221,6 @@
 };
 
 // PR5139
-// CHECK: @_ZN2S7C1Ev
 // CHECK: @_ZN2S7C2Ev
 // CHECK: @"_ZN2S73$_0C1Ev"
 S7::S7() {}

Modified: cfe/trunk/test/CodeGenCXX/member-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/member-templates.cpp?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/member-templates.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/member-templates.cpp Tue Feb 16 21:52:49 2010
@@ -15,7 +15,7 @@
 
 template<typename T> B::B(T) {}
 
-// CHECK: define void @_ZN1BC1IiEET_(%struct.B* %this, i32)
+// CHECK: @_ZN1BC1IiEET_ = alias {{.*}} @_ZN1BC2IiEET_
 // CHECK: define void @_ZN1BC2IiEET_(%struct.B* %this, i32)
 template B::B(int);
 

Modified: cfe/trunk/test/CodeGenCXX/virtual-bases.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virtual-bases.cpp?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/virtual-bases.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/virtual-bases.cpp Tue Feb 16 21:52:49 2010
@@ -4,7 +4,7 @@
   A();
 };
 
-// CHECK: define void @_ZN1AC1Ev(%struct.A* %this)
+// CHECK: @_ZN1AC1Ev = alias {{.*}} @_ZN1AC2Ev
 // CHECK: define void @_ZN1AC2Ev(%struct.A* %this)
 A::A() { }
 
@@ -12,14 +12,14 @@
   B();
 };
 
-// CHECK: define void @_ZN1BC1Ev(%struct.B* %this)
 // CHECK: define void @_ZN1BC2Ev(%struct.B* %this, i8** %vtt)
+// CHECK: define void @_ZN1BC1Ev(%struct.B* %this)
 B::B() { }
 
 struct C : virtual A {
   C(bool);
 };
 
-// CHECK: define void @_ZN1CC1Eb(%struct.B* %this, i1 zeroext)
 // CHECK: define void @_ZN1CC2Eb(%struct.B* %this, i8** %vtt, i1 zeroext)
+// CHECK: define void @_ZN1CC1Eb(%struct.B* %this, i1 zeroext)
 C::C(bool) { }

Modified: cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp Tue Feb 16 21:52:49 2010
@@ -9,8 +9,7 @@
 };
 
 // Complete dtor.
-// CHECK: define void @_ZN1BD1Ev
-// CHECK: call void @_ZN1AD2Ev
+// CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev
 
 // Deleting dtor.
 // CHECK: define void @_ZN1BD0Ev

Modified: cfe/trunk/test/CodeGenCXX/vtable-pointer-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-pointer-initialization.cpp?rev=96451&r1=96450&r2=96451&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/vtable-pointer-initialization.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/vtable-pointer-initialization.cpp Tue Feb 16 21:52:49 2010
@@ -19,14 +19,14 @@
   Field field;
 };
 
-// CHECK: define void @_ZN1AC1Ev(
+// CHECK: define void @_ZN1AC2Ev(
 // CHECK: call void @_ZN4BaseC2Ev(
 // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
 // CHECK: call void @_ZN5FieldC1Ev(
 // CHECK: ret void
 A::A() { }
 
-// CHECK: define void @_ZN1AD1Ev(
+// CHECK: define void @_ZN1AD2Ev(
 // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
 // CHECK: call void @_ZN5FieldD1Ev(
 // CHECK: call void @_ZN4BaseD2Ev(





More information about the cfe-commits mailing list