Ping. It is essential to build selfhost clang on cygming. I wonder, for now, if it were enabled not with --fno-use-cxa-atexit, but triple=cygming.
...Takumi
commit 566ce3718dc3932d009a8aa977fc3d794da3925d (HEAD) Author: NAKAMURA Takumi <[email protected]> Date: Wed Mar 28 16:22:33 2012 [PR9593] Rework -fno-use-cxa-atexit not to invoke local dtors unconditionally, but use atexit(). -fno-use-cxa-atexit is by default on cygming, due to unavailability of __cxa_atexit(). diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index dc52b11..6387407 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -148,9 +148,13 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, void CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, llvm::Constant *DeclPtr) { - // Generate a global destructor entry if not using __cxa_atexit. if (!CGM.getCodeGenOpts().CXAAtExit) { - CGM.AddCXXDtorEntry(DtorFn, DeclPtr); + if (CGM.getContext().getLangOpts().AppleKext) + // Generate a global destructor entry. + CGM.AddCXXDtorEntry(DtorFn, DeclPtr); + else + // Generate atexit(). + EmitCXXAtExitGlobalDtor(DtorFn, DeclPtr); return; } @@ -178,6 +182,26 @@ CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, Builder.CreateCall(AtExitFn, Args); } +void +CodeGenFunction::EmitCXXAtExitGlobalDtor(llvm::Constant *DtorFn, + llvm::Constant *DeclPtr) { + // Generate "call void __dtor_() {DeclPtr->~DtorFn();}". + DtorFn = CodeGenFunction(CGM).GenerateCXXGlobalDtorFunc(DtorFn, DeclPtr); + + // extern "C" int atexit(void (*)(void)); + llvm::FunctionType *AtExitFnTy = + llvm::FunctionType::get(ConvertType(getContext().IntTy), + DtorFn->getType(), + false); + + llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, + "atexit"); + if (llvm::Function *Fn = dyn_cast<llvm::Function>(AtExitFn)) + Fn->setDoesNotThrow(); + + Builder.CreateCall(AtExitFn, DtorFn); +} + void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D, llvm::GlobalVariable *DeclPtr, bool PerformInit) { @@ -290,7 +314,7 @@ void CodeGenModule::EmitCXXGlobalDtorFunc() { llvm::Function *Fn = CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a"); - CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors); + CodeGenFunction(*this).GenerateCXXGlobalDtorsFunc(Fn, CXXGlobalDtors); AddGlobalDtor(Fn); } @@ -341,7 +365,7 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, FinishFunction(); } -void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, +void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn, const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> > &DtorsAndObjects) { StartFunction(GlobalDecl(), getContext().VoidTy, Fn, @@ -361,6 +385,32 @@ void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, FinishFunction(); } +llvm::Function * +CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Constant *DtorFn, + llvm::Constant *DeclPtr) { + // Get the destructor function type + // Internal void __dtor_DeclPtr(void) + llvm::FunctionType *FTy = + llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), + false); + llvm::Function *Fn = + CreateGlobalInitOrDestructFunction(CGM, FTy, + Twine("__dtor_", DeclPtr->getName())); + + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, + getTypes().arrangeNullaryFunction(), + FunctionArgList(), SourceLocation()); + + llvm::CallInst *CI = Builder.CreateCall(DtorFn, DeclPtr); + // Make sure the call and the callee agree on calling convention. + if (llvm::Function *F = dyn_cast<llvm::Function>(DtorFn)) + CI->setCallingConv(F->getCallingConv()); + + FinishFunction(); + + return Fn; +} + /// generateDestroyHelper - Generates a helper function which, when /// invoked, destroys the given object. llvm::Function * diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 85cbd14..e70f329 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2414,6 +2414,10 @@ public: /// with the C++ runtime so that its destructor will be called at exit. void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, llvm::Constant *DeclPtr); + /// EmitCXXAtExitGlobalDtor - Creates a call to atexit() + /// that a function "void __dtor_DeclPtr() {DeclPtr->~DtorFn();}". + void EmitCXXAtExitGlobalDtor(llvm::Constant *DtorFn, + llvm::Constant *DeclPtr); /// Emit code in this function to perform a guarded variable /// initialization. Guarded initializations are used when it's not @@ -2429,11 +2433,13 @@ public: llvm::Constant **Decls, unsigned NumDecls); - /// GenerateCXXGlobalDtorFunc - Generates code for destroying global + /// GenerateCXXGlobalDtorsFunc - Generates code for destroying global /// variables. - void GenerateCXXGlobalDtorFunc(llvm::Function *Fn, - const std::vector<std::pair<llvm::WeakVH, - llvm::Constant*> > &DtorsAndObjects); + void GenerateCXXGlobalDtorsFunc(llvm::Function *Fn, + const std::vector<std::pair<llvm::WeakVH, + llvm::Constant*> > &DtorsAndObjects); + llvm::Function *GenerateCXXGlobalDtorFunc(llvm::Constant *DtorFn, + llvm::Constant *DeclPtr); void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D, diff --git a/clang/test/CodeGenCXX/arm.cpp b/clang/test/CodeGenCXX/arm.cpp index 36c6c1c..d3c77f8 100644 --- a/clang/test/CodeGenCXX/arm.cpp +++ b/clang/test/CodeGenCXX/arm.cpp @@ -20,9 +20,17 @@ public: // The global dtor needs the right calling conv with -fno-use-cxa-atexit // rdar://7817590 -// Checked at end of file. bar baz; +// PR9593 +// Make sure atexit(3) is used for global dtors. + +// CHECK: call %class.bar* @_ZN3barC1Ev(%class.bar* @baz) +// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_baz) + +// CHECK: define internal void @__dtor_baz() +// CHECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz) + // Destructors and constructors must return this. namespace test1 { void foo(); @@ -357,5 +365,5 @@ namespace test8 { // CHECK: call void @_ZN5test21CD0Ev( // CHECK: ret void -// CHECK: @_GLOBAL__D_a() -// CHECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz) +// CH_ECK: @_GLOBAL__D_a() +// CH_ECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz) diff --git a/clang/test/CodeGenCXX/global-dtor-no-atexit.cpp b/clang/test/CodeGenCXX/global-dtor-no-atexit.cpp index 1e125e3..0ba5115 100644 --- a/clang/test/CodeGenCXX/global-dtor-no-atexit.cpp +++ b/clang/test/CodeGenCXX/global-dtor-no-atexit.cpp @@ -3,10 +3,15 @@ // PR7097 // RUN: %clang_cc1 -triple x86_64 %s -fno-use-cxa-atexit -mconstructor-aliases -emit-llvm -o - | FileCheck %s -// CHECK: define internal void @_GLOBAL__D_a() -// CHECK: call void @_ZN1AD1Ev(%class.A* @b) -// CHECK: call void @_ZN1AD1Ev(%class.A* @a) -// CHECK: } +// CHECK: call void @_ZN1AC1Ev(%class.A* @a) +// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_a) +// CHECK: define internal void @__dtor_a() nounwind +// CHECK: call void @_ZN1AD1Ev(%class.A* @a) + +// CHECK: call void @_ZN1AC1Ev(%class.A* @b) +// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_b) +// CHECK: define internal void @__dtor_b() nounwind +// CHECK: call void @_ZN1AD1Ev(%class.A* @b) class A { public: @@ -15,3 +20,25 @@ public: }; A a, b; + +// PR9593 +// CHECK: define void @_Z4funcv() +// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZ4funcvE2a1) +// CHECK: call void @_ZN1AC1Ev(%class.A* @_ZZ4funcvE2a1) +// CHECK-NEXT: call i32 @atexit(void ()* @__dtor__ZZ4funcvE2a1) +// CHECK-NEXT: call void @__cxa_guard_release(i64* @_ZGVZ4funcvE2a1) + +// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZ4funcvE2a2) +// CHECK: call void @_ZN1AC1Ev(%class.A* @_ZZ4funcvE2a2) +// CHECK-NEXT: call i32 @atexit(void ()* @__dtor__ZZ4funcvE2a2) +// CHECK-NEXT: call void @__cxa_guard_release(i64* @_ZGVZ4funcvE2a2) + +// CHECK: define internal void @__dtor__ZZ4funcvE2a1() nounwind +// CHECK: call void @_ZN1AD1Ev(%class.A* @_ZZ4funcvE2a1) + +// CHECK: define internal void @__dtor__ZZ4funcvE2a2() nounwind +// CHECK: call void @_ZN1AD1Ev(%class.A* @_ZZ4funcvE2a2) + +void func() { + static A a1, a2; +}
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
