r194000 - Use aliases for more constructors and destructors.

Yaron Keren yaron.keren at gmail.com
Tue Nov 5 01:28:58 PST 2013


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>

> 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
> 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/fcad2268/attachment.html>


More information about the cfe-commits mailing list