Hi, This patch causes
Assertion failed: !isAlreadyCodeGenerating && "Error: Recursive compilation detected!", file ..\..\..\..\lib\ExecutionEngine\JIT\JIT.cpp, line 467 and fixed by setting getCodeGenOpts().CXXCtorDtorAliases = 0; Is this the right fix or should something else in the JIT logic be modified? Yaron 2013/11/4 Rafael Espindola <[email protected]> > Author: rafael > Date: Mon Nov 4 12:38:59 2013 > New Revision: 194000 > > URL: http://llvm.org/viewvc/llvm-project?rev=194000&view=rev > Log: > Use aliases for more constructors and destructors. > > With this patch we produce alias for cases like > > template<typename T> > struct foobar { > foobar() { > } > }; > template struct foobar<void>; > > We just have to be careful to produce the same aliases in every TU because > of comdats. > > Added: > cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp > Modified: > cfe/trunk/lib/CodeGen/CGCXX.cpp > cfe/trunk/lib/CodeGen/CGVTables.cpp > cfe/trunk/lib/CodeGen/CodeGenModule.h > cfe/trunk/test/CodeGenCXX/destructors.cpp > > Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=194000&r1=193999&r2=194000&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGCXX.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGCXX.cpp Mon Nov 4 12:38:59 2013 > @@ -95,12 +95,16 @@ bool CodeGenModule::TryEmitBaseDestructo > return true; > > return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base), > - GlobalDecl(BaseD, Dtor_Base)); > + GlobalDecl(BaseD, Dtor_Base), > + false); > } > > /// Try to emit a definition as a global alias for another definition. > +/// If \p InEveryTU is true, we know that an equivalent alias can be > produced > +/// in every translation unit. > bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, > - GlobalDecl TargetDecl) { > + GlobalDecl TargetDecl, > + bool InEveryTU) { > if (!getCodeGenOpts().CXXCtorDtorAliases) > return true; > > @@ -108,34 +112,34 @@ bool CodeGenModule::TryEmitDefinitionAsA > // support aliases with that linkage, fail. > llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl); > > - 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; > - } > - > llvm::GlobalValue::LinkageTypes TargetLinkage > = getFunctionLinkage(TargetDecl); > > - if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) > + // Don't create an alias to a linker weak symbol unless we know we can > do > + // that in every TU. This avoids producing different COMDATs in > different > + // TUs. > + if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) { > + if (!InEveryTU) > + return true; > + > + // In addition to making sure we produce it in every TU, we have to > make > + // sure llvm keeps it. > + // FIXME: Instead of outputting an alias we could just replace every > use of > + // AliasDecl with TargetDecl. > + assert(Linkage == TargetLinkage); > + Linkage = llvm::GlobalValue::WeakODRLinkage; > + } > + > + // We can't use an alias if the linkage is not valid for one. > + if (!llvm::GlobalAlias::isValidLinkage(Linkage)) > return true; > > + // Check if we have it already. > + StringRef MangledName = getMangledName(AliasDecl); > + llvm::GlobalValue *Entry = GetGlobalValue(MangledName); > + if (Entry && !Entry->isDeclaration()) > + return false; > + > // Derive the type for the alias. > llvm::PointerType *AliasType > = getTypes().GetFunctionType(AliasDecl)->getPointerTo(); > @@ -153,10 +157,7 @@ bool CodeGenModule::TryEmitDefinitionAsA > new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule()); > > // Switch any previous uses to the alias. > - StringRef MangledName = getMangledName(AliasDecl); > - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); > if (Entry) { > - assert(Entry->isDeclaration() && "definition already exists for > alias"); > assert(Entry->getType() == AliasType && > "declaration exists with different type"); > Alias->takeName(Entry); > @@ -177,11 +178,14 @@ void CodeGenModule::EmitCXXConstructor(c > // The complete constructor is equivalent to the base constructor > // for classes with no virtual bases. Try to emit it as an alias. > if (getTarget().getCXXABI().hasConstructorVariants() && > - ctorType == Ctor_Complete && > !ctor->getParent()->getNumVBases() && > - !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete), > - GlobalDecl(ctor, Ctor_Base))) > - return; > + (ctorType == Ctor_Complete || ctorType == Ctor_Base)) { > + bool ProducedAlias = > + !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete), > + GlobalDecl(ctor, Ctor_Base), true); > + if (ctorType == Ctor_Complete && ProducedAlias) > + return; > + } > > const CGFunctionInfo &fnInfo = > getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType); > @@ -218,11 +222,18 @@ void CodeGenModule::EmitCXXDestructor(co > CXXDtorType dtorType) { > // The complete destructor is equivalent to the base destructor for > // classes with no virtual bases, so try to emit it as an alias. > - if (dtorType == Dtor_Complete && > - !dtor->getParent()->getNumVBases() && > - !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete), > - GlobalDecl(dtor, Dtor_Base))) > - return; > + if (!dtor->getParent()->getNumVBases() && > + (dtorType == Dtor_Complete || dtorType == Dtor_Base)) { > + bool ProducedAlias = > + !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete), > + GlobalDecl(dtor, Dtor_Base), true); > + if (ProducedAlias) { > + if (dtorType == Dtor_Complete) > + return; > + if (dtor->isVirtual()) > + getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete)); > + } > + } > > // The base destructor is equivalent to the base destructor of its > // base class if there is exactly one non-virtual base class with a > > Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=194000&r1=193999&r2=194000&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGVTables.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGVTables.cpp Mon Nov 4 12:38:59 2013 > @@ -387,10 +387,6 @@ void CodeGenVTables::emitThunk(GlobalDec > return; > } > > - // If a function has a body, it should have available_externally > linkage. > - assert(ThunkFn->hasAvailableExternallyLinkage() && > - "Function should have available_externally linkage!"); > - > // Change the linkage. > CGM.setFunctionLinkage(GD, ThunkFn); > return; > > Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=194000&r1=193999&r2=194000&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original) > +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Nov 4 12:38:59 2013 > @@ -1034,7 +1034,8 @@ private: > > // C++ related functions. > > - bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target); > + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, > + bool InEveryTU); > bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); > > void EmitNamespace(const NamespaceDecl *D); > > Added: cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp?rev=194000&view=auto > > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp (added) > +++ cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp Mon Nov 4 12:38:59 2013 > @@ -0,0 +1,62 @@ > +// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - > -mconstructor-aliases | FileCheck %s > + > +namespace test1 { > +// test that we produce an alias when the destructor is weak_odr > + > +// CHECK-DAG: @_ZN5test16foobarIvEC1Ev = alias weak_odr void > (%"struct.test1::foobar"*)* @_ZN5test16foobarIvEC2Ev > +// CHECK-DAG: define weak_odr void @_ZN5test16foobarIvEC2Ev( > +template <typename T> struct foobar { > + foobar() {} > +}; > + > +template struct foobar<void>; > +} > + > +namespace test2 { > +// test that we produce an alias when the destrucor is linkonce_odr. Note > that > +// the alias itself is weak_odr to make sure we don't get a translation > unit > +// with just _ZN5test26foobarIvEC2Ev in it. > + > +// CHECK-DAG: @_ZN5test26foobarIvEC1Ev = alias weak_odr void > (%"struct.test2::foobar"*)* @_ZN5test26foobarIvEC2Ev > +// CHECK-DAG: define linkonce_odr void @_ZN5test26foobarIvEC2Ev( > +void g(); > +template <typename T> struct foobar { > + foobar() { g(); } > +}; > +foobar<void> x; > +} > + > +namespace test3 { > +// test that these alias are internal. > + > +// CHECK-DAG: @_ZN5test312_GLOBAL__N_11AD1Ev = alias internal void > (%"struct.test3::<anonymous namespace>::A"*)* @_ZN5test312_GLOBAL__N_11AD2Ev > +// 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"*)*) > +// CHECK-DAG: @_ZN5test312_GLOBAL__N_11BD1Ev = alias internal void > (%"struct.test3::<anonymous namespace>::B"*)* @_ZN5test312_GLOBAL__N_11BD2Ev > +// CHECK-DAG: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev( > +namespace { > +struct A { > + ~A() {} > +}; > + > +struct B : public A {}; > +} > + > +B x; > +} > + > +namespace test4 { > + // Test that we don't produce aliases from B to A. We cannot because we > cannot > + // guarantee that they will be present in every TU. > + > + // CHECK-DAG: @_ZN5test41BD1Ev = alias weak_odr void > (%"struct.test4::B"*)* @_ZN5test41BD2Ev > + // CHECK-DAG: define linkonce_odr void @_ZN5test41BD2Ev( > + // CHECK-DAG: @_ZN5test41AD1Ev = alias weak_odr void > (%"struct.test4::A"*)* @_ZN5test41AD2Ev > + // CHECK-DAG: define linkonce_odr void @_ZN5test41AD2Ev( > + struct A { > + virtual ~A() {} > + }; > + struct B : public A{ > + ~B() {} > + }; > + B X; > +} > > Modified: cfe/trunk/test/CodeGenCXX/destructors.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/destructors.cpp?rev=194000&r1=193999&r2=194000&view=diff > > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/destructors.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/destructors.cpp Mon Nov 4 12:38:59 2013 > @@ -9,6 +9,7 @@ > // CHECK-DAG: @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} > @_ZN5test312_GLOBAL__N_11DD2Ev > // CHECK-DAG: @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast > {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev > // CHECK-DAG: @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} > @_ZN5test312_GLOBAL__N_11CD2Ev > +// CHECK-DAG: @_ZN6PR752617allocator_derivedD1Ev = alias weak_odr void > (%"struct.PR7526::allocator_derived"*)* @_ZN6PR752617allocator_derivedD2Ev > > struct A { > int a; > @@ -44,9 +45,6 @@ namespace PR7526 { > // CHECK: call void @__cxa_call_unexpected > allocator::~allocator() throw() { foo(); } > > - // CHECK-LABEL: define linkonce_odr void > @_ZN6PR752617allocator_derivedD1Ev(%"struct.PR7526::allocator_derived"* > %this) unnamed_addr > - // CHECK-NOT: call void @__cxa_call_unexpected > - // CHECK: } > void foo() { > allocator_derived ad; > } > @@ -396,6 +394,11 @@ namespace test9 { > // CHECK: call void @_ZN5test31AD2Ev( > // CHECK: ret void > > + // CHECK-LABEL: define internal void > @_ZThn8_N5test312_GLOBAL__N_11CD1Ev( > + // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 > + // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev( > + // CHECK: ret void > + > // CHECK: declare void @_ZN5test31BD2Ev( > // CHECK: declare void @_ZN5test31AD2Ev( > > @@ -408,11 +411,6 @@ namespace test9 { > // CHECK: call void @_ZdlPv({{.*}}) [[NUW]] > // CHECK: resume { i8*, i32 } > > - // CHECK-LABEL: define internal void > @_ZThn8_N5test312_GLOBAL__N_11CD1Ev( > - // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 > - // CHECK: call void @_ZN5test312_GLOBAL__N_11CD1Ev( > - // CHECK: ret void > - > // CHECK-LABEL: define internal void > @_ZThn8_N5test312_GLOBAL__N_11CD0Ev( > // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 > // CHECK: call void @_ZN5test312_GLOBAL__N_11CD0Ev( > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
