r194000 - Use aliases for more constructors and destructors.
Rafael EspĂndola
rafael.espindola at gmail.com
Tue Nov 5 07:18:53 PST 2013
Can you provide a test case? Could you also try the patch I emailed about
using the aliasee directly when possible?
On Tuesday, November 5, 2013, Yaron Keren wrote:
> 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 <rafael.espindola at gmail.com <javascript:_e({},
> 'cvml', 'rafael.espindola at gmail.com');>>
>
>> 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
>> cfe-commits at cs.uiuc.edu <javascript:_e({}, 'cvml',
>> 'cfe-commits at cs.uiuc.edu');>
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131105/be595538/attachment.html>
More information about the cfe-commits
mailing list