<div dir="rtl"><div dir="ltr">Hi,</div><div dir="ltr"><br></div><div dir="ltr">This patch causes</div><div dir="ltr"><br></div><div dir="ltr"><div dir="ltr"><font face="courier new, monospace"> Assertion failed: !isAlreadyCodeGenerating && "Error: Recursive compilation detected!", file ..\..\..\..\lib\ExecutionEngine\JIT\JIT.cpp, line 467</font></div>

</div><div class="gmail_extra"><br></div><div class="gmail_extra"><div dir="ltr">and fixed by setting</div><div dir="ltr"><br></div><div dir="ltr"><font face="courier new, monospace"> getCodeGenOpts().CXXCtorDtorAliases = 0;</font></div>

<div dir="ltr"><br></div><div dir="ltr">Is this the right fix or should something else in the JIT logic be modified?</div><div dir="ltr"><br></div><div dir="ltr">Yaron</div><div dir="ltr"><br><br></div><div class="gmail_quote">

<div dir="ltr">2013/11/4 Rafael Espindola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.com</a>></span></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

Author: rafael<br>
Date: Mon Nov  4 12:38:59 2013<br>
New Revision: 194000<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=194000&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=194000&view=rev</a><br>
Log:<br>
Use aliases for more constructors and destructors.<br>
<br>
With this patch we produce alias for cases like<br>
<br>
template<typename T><br>
struct foobar {<br>
  foobar() {<br>
  }<br>
};<br>
template struct foobar<void>;<br>
<br>
We just have to be careful to produce the same aliases in every TU because<br>
of comdats.<br>
<br>
Added:<br>
    cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CGCXX.cpp<br>
    cfe/trunk/lib/CodeGen/CGVTables.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
    cfe/trunk/test/CodeGenCXX/destructors.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=194000&r1=193999&r2=194000&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=194000&r1=193999&r2=194000&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Mon Nov  4 12:38:59 2013<br>
@@ -95,12 +95,16 @@ bool CodeGenModule::TryEmitBaseDestructo<br>
     return true;<br>
<br>
   return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),<br>
-                                  GlobalDecl(BaseD, Dtor_Base));<br>
+                                  GlobalDecl(BaseD, Dtor_Base),<br>
+                                  false);<br>
 }<br>
<br>
 /// Try to emit a definition as a global alias for another definition.<br>
+/// If \p InEveryTU is true, we know that an equivalent alias can be produced<br>
+/// in every translation unit.<br>
 bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,<br>
-                                             GlobalDecl TargetDecl) {<br>
+                                             GlobalDecl TargetDecl,<br>
+                                             bool InEveryTU) {<br>
   if (!getCodeGenOpts().CXXCtorDtorAliases)<br>
     return true;<br>
<br>
@@ -108,34 +112,34 @@ bool CodeGenModule::TryEmitDefinitionAsA<br>
   // support aliases with that linkage, fail.<br>
   llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);<br>
<br>
-  switch (Linkage) {<br>
-  // We can definitely emit aliases to definitions with external linkage.<br>
-  case llvm::GlobalValue::ExternalLinkage:<br>
-  case llvm::GlobalValue::ExternalWeakLinkage:<br>
-    break;<br>
-<br>
-  // Same with local linkage.<br>
-  case llvm::GlobalValue::InternalLinkage:<br>
-  case llvm::GlobalValue::PrivateLinkage:<br>
-  case llvm::GlobalValue::LinkerPrivateLinkage:<br>
-    break;<br>
-<br>
-  // We should try to support linkonce linkages.<br>
-  case llvm::GlobalValue::LinkOnceAnyLinkage:<br>
-  case llvm::GlobalValue::LinkOnceODRLinkage:<br>
-    return true;<br>
-<br>
-  // Other linkages will probably never be supported.<br>
-  default:<br>
-    return true;<br>
-  }<br>
-<br>
   llvm::GlobalValue::LinkageTypes TargetLinkage<br>
     = getFunctionLinkage(TargetDecl);<br>
<br>
-  if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))<br>
+  // Don't create an alias to a linker weak symbol unless we know we can do<br>
+  // that in every TU. This avoids producing different COMDATs in different<br>
+  // TUs.<br>
+  if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) {<br>
+    if (!InEveryTU)<br>
+      return true;<br>
+<br>
+    // In addition to making sure we produce it in every TU, we have to make<br>
+    // sure llvm keeps it.<br>
+    // FIXME: Instead of outputting an alias we could just replace every use of<br>
+    // AliasDecl with TargetDecl.<br>
+    assert(Linkage == TargetLinkage);<br>
+    Linkage = llvm::GlobalValue::WeakODRLinkage;<br>
+  }<br>
+<br>
+  // We can't use an alias if the linkage is not valid for one.<br>
+  if (!llvm::GlobalAlias::isValidLinkage(Linkage))<br>
     return true;<br>
<br>
+  // Check if we have it already.<br>
+  StringRef MangledName = getMangledName(AliasDecl);<br>
+  llvm::GlobalValue *Entry = GetGlobalValue(MangledName);<br>
+  if (Entry && !Entry->isDeclaration())<br>
+    return false;<br>
+<br>
   // Derive the type for the alias.<br>
   llvm::PointerType *AliasType<br>
     = getTypes().GetFunctionType(AliasDecl)->getPointerTo();<br>
@@ -153,10 +157,7 @@ bool CodeGenModule::TryEmitDefinitionAsA<br>
     new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());<br>
<br>
   // Switch any previous uses to the alias.<br>
-  StringRef MangledName = getMangledName(AliasDecl);<br>
-  llvm::GlobalValue *Entry = GetGlobalValue(MangledName);<br>
   if (Entry) {<br>
-    assert(Entry->isDeclaration() && "definition already exists for alias");<br>
     assert(Entry->getType() == AliasType &&<br>
            "declaration exists with different type");<br>
     Alias->takeName(Entry);<br>
@@ -177,11 +178,14 @@ void CodeGenModule::EmitCXXConstructor(c<br>
   // The complete constructor is equivalent to the base constructor<br>
   // for classes with no virtual bases.  Try to emit it as an alias.<br>
   if (getTarget().getCXXABI().hasConstructorVariants() &&<br>
-      ctorType == Ctor_Complete &&<br>
       !ctor->getParent()->getNumVBases() &&<br>
-      !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),<br>
-                                GlobalDecl(ctor, Ctor_Base)))<br>
-    return;<br>
+      (ctorType == Ctor_Complete || ctorType == Ctor_Base)) {<br>
+    bool ProducedAlias =<br>
+        !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),<br>
+                                  GlobalDecl(ctor, Ctor_Base), true);<br>
+    if (ctorType == Ctor_Complete && ProducedAlias)<br>
+      return;<br>
+  }<br>
<br>
   const CGFunctionInfo &fnInfo =<br>
     getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);<br>
@@ -218,11 +222,18 @@ void CodeGenModule::EmitCXXDestructor(co<br>
                                       CXXDtorType dtorType) {<br>
   // The complete destructor is equivalent to the base destructor for<br>
   // classes with no virtual bases, so try to emit it as an alias.<br>
-  if (dtorType == Dtor_Complete &&<br>
-      !dtor->getParent()->getNumVBases() &&<br>
-      !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete),<br>
-                                GlobalDecl(dtor, Dtor_Base)))<br>
-    return;<br>
+  if (!dtor->getParent()->getNumVBases() &&<br>
+      (dtorType == Dtor_Complete || dtorType == Dtor_Base)) {<br>
+    bool ProducedAlias =<br>
+        !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete),<br>
+                                  GlobalDecl(dtor, Dtor_Base), true);<br>
+    if (ProducedAlias) {<br>
+      if (dtorType == Dtor_Complete)<br>
+        return;<br>
+      if (dtor->isVirtual())<br>
+        getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete));<br>
+    }<br>
+  }<br>
<br>
   // The base destructor is equivalent to the base destructor of its<br>
   // base class if there is exactly one non-virtual base class with a<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=194000&r1=193999&r2=194000&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=194000&r1=193999&r2=194000&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Mon Nov  4 12:38:59 2013<br>
@@ -387,10 +387,6 @@ void CodeGenVTables::emitThunk(GlobalDec<br>
       return;<br>
     }<br>
<br>
-    // If a function has a body, it should have available_externally linkage.<br>
-    assert(ThunkFn->hasAvailableExternallyLinkage() &&<br>
-           "Function should have available_externally linkage!");<br>
-<br>
     // Change the linkage.<br>
     CGM.setFunctionLinkage(GD, ThunkFn);<br>
     return;<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=194000&r1=193999&r2=194000&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=194000&r1=193999&r2=194000&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Nov  4 12:38:59 2013<br>
@@ -1034,7 +1034,8 @@ private:<br>
<br>
   // C++ related functions.<br>
<br>
-  bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);<br>
+  bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target,<br>
+                                bool InEveryTU);<br>
   bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);<br>
<br>
   void EmitNamespace(const NamespaceDecl *D);<br>
<br>
Added: cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp?rev=194000&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp?rev=194000&view=auto</a><br>


==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp (added)<br>
+++ cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp Mon Nov  4 12:38:59 2013<br>
@@ -0,0 +1,62 @@<br>
+// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases | FileCheck %s<br>
+<br>
+namespace test1 {<br>
+// test that we produce an alias when the destructor is weak_odr<br>
+<br>
+// CHECK-DAG: @_ZN5test16foobarIvEC1Ev = alias weak_odr void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvEC2Ev<br>
+// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC2Ev(<br>
+template <typename T> struct foobar {<br>
+  foobar() {}<br>
+};<br>
+<br>
+template struct foobar<void>;<br>
+}<br>
+<br>
+namespace test2 {<br>
+// test that we produce an alias when the destrucor is linkonce_odr. Note that<br>
+// the alias itself is weak_odr to make sure we don't get a translation unit<br>
+// with just _ZN5test26foobarIvEC2Ev in it.<br>
+<br>
+// CHECK-DAG: @_ZN5test26foobarIvEC1Ev = alias weak_odr void (%"struct.test2::foobar"*)* @_ZN5test26foobarIvEC2Ev<br>
+// CHECK-DAG: define linkonce_odr void @_ZN5test26foobarIvEC2Ev(<br>
+void g();<br>
+template <typename T> struct foobar {<br>
+  foobar() { g(); }<br>
+};<br>
+foobar<void> x;<br>
+}<br>
+<br>
+namespace test3 {<br>
+// test that these alias are internal.<br>
+<br>
+// CHECK-DAG: @_ZN5test312_GLOBAL__N_11AD1Ev = alias internal void (%"struct.test3::<anonymous namespace>::A"*)* @_ZN5test312_GLOBAL__N_11AD2Ev<br>
+// CHECK-DAG: @_ZN5test312_GLOBAL__N_11BD2Ev = alias internal bitcast (void (%"struct.test3::<anonymous namespace>::A"*)* @_ZN5test312_GLOBAL__N_11AD2Ev to void (%"struct.test3::<anonymous namespace>::B"*)*)<br>


+// CHECK-DAG: @_ZN5test312_GLOBAL__N_11BD1Ev = alias internal void (%"struct.test3::<anonymous namespace>::B"*)* @_ZN5test312_GLOBAL__N_11BD2Ev<br>
+// CHECK-DAG: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev(<br>
+namespace {<br>
+struct A {<br>
+  ~A() {}<br>
+};<br>
+<br>
+struct B : public A {};<br>
+}<br>
+<br>
+B x;<br>
+}<br>
+<br>
+namespace test4 {<br>
+  // Test that we don't produce aliases from B to A. We cannot because we cannot<br>
+  // guarantee that they will be present in every TU.<br>
+<br>
+  // CHECK-DAG: @_ZN5test41BD1Ev = alias weak_odr void (%"struct.test4::B"*)* @_ZN5test41BD2Ev<br>
+  // CHECK-DAG: define linkonce_odr void @_ZN5test41BD2Ev(<br>
+  // CHECK-DAG: @_ZN5test41AD1Ev = alias weak_odr void (%"struct.test4::A"*)* @_ZN5test41AD2Ev<br>
+  // CHECK-DAG: define linkonce_odr void @_ZN5test41AD2Ev(<br>
+  struct A {<br>
+    virtual ~A() {}<br>
+  };<br>
+  struct B : public A{<br>
+    ~B() {}<br>
+  };<br>
+  B X;<br>
+}<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/destructors.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/destructors.cpp?rev=194000&r1=193999&r2=194000&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/destructors.cpp?rev=194000&r1=193999&r2=194000&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/destructors.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/destructors.cpp Mon Nov  4 12:38:59 2013<br>
@@ -9,6 +9,7 @@<br>
 // CHECK-DAG: @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev<br>
 // CHECK-DAG: @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev<br>
 // CHECK-DAG: @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev<br>
+// CHECK-DAG: @_ZN6PR752617allocator_derivedD1Ev = alias weak_odr void (%"struct.PR7526::allocator_derived"*)* @_ZN6PR752617allocator_derivedD2Ev<br>
<br>
 struct A {<br>
   int a;<br>
@@ -44,9 +45,6 @@ namespace PR7526 {<br>
   // CHECK: call void @__cxa_call_unexpected<br>
   allocator::~allocator() throw() { foo(); }<br>
<br>
-  // CHECK-LABEL: define linkonce_odr void @_ZN6PR752617allocator_derivedD1Ev(%"struct.PR7526::allocator_derived"* %this) unnamed_addr<br>
-  // CHECK-NOT: call void @__cxa_call_unexpected<br>
-  // CHECK:     }<br>
   void foo() {<br>
     allocator_derived ad;<br>
   }<br>
@@ -396,6 +394,11 @@ namespace test9 {<br>
   // CHECK: call void @_ZN5test31AD2Ev(<br>
   // CHECK: ret void<br>
<br>
+  // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(<br>
+  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8<br>
+  // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev(<br>
+  // CHECK: ret void<br>
+<br>
   // CHECK: declare void @_ZN5test31BD2Ev(<br>
   // CHECK: declare void @_ZN5test31AD2Ev(<br>
<br>
@@ -408,11 +411,6 @@ namespace test9 {<br>
   // CHECK: call void @_ZdlPv({{.*}}) [[NUW]]<br>
   // CHECK: resume { i8*, i32 }<br>
<br>
-  // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(<br>
-  // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8<br>
-  // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev(<br>
-  // CHECK: ret void<br>
-<br>
   // CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD0Ev(<br>
   // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8<br>
   // CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev(<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>