[cfe-commits] r154191 - in /cfe/trunk: lib/CodeGen/CGDeclCXX.cpp test/CodeGenCXX/arm.cpp test/CodeGenCXX/global-dtor-no-atexit.cpp test/CodeGenCXX/global-init.cpp test/CodeGenCXX/static-init.cpp
Nico Weber
thakis at chromium.org
Mon May 5 21:30:23 PDT 2014
Hi John,
sorry about the years-delayed reply. Does test/CodeGenCXX/arm.cpp
intentionally say "CH_ECK" instead of "CHECK" in the last 2 lines? (If
I change the test to say "CHECK", it fails, at least.)
Thanks,
Nico
On Fri, Apr 6, 2012 at 11:21 AM, John McCall <rjmccall at apple.com> wrote:
> Author: rjmccall
> Date: Fri Apr 6 13:21:06 2012
> New Revision: 154191
>
> URL: http://llvm.org/viewvc/llvm-project?rev=154191&view=rev
> Log:
> Use atexit when __cxa_atexit isn't available instead of adding a
> global destructor entry. For some reason this isn't enabled for
> apple-kexts; it'd be good to have documentation for that.
>
> Based on a patch by Nakamura Takumi!
>
> Modified:
> cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
> cfe/trunk/test/CodeGenCXX/arm.cpp
> cfe/trunk/test/CodeGenCXX/global-dtor-no-atexit.cpp
> cfe/trunk/test/CodeGenCXX/global-init.cpp
> cfe/trunk/test/CodeGenCXX/static-init.cpp
>
> Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=154191&r1=154190&r2=154191&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Fri Apr 6 13:21:06 2012
> @@ -145,37 +145,109 @@
> EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
> }
>
> -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);
> +/// Register a global destructor using __cxa_atexit.
> +static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
> + llvm::Constant *dtor,
> + llvm::Constant *addr) {
> + // We're assuming that the destructor function is something we can
> + // reasonably call with the default CC. Go ahead and cast it to the
> + // right prototype.
> + llvm::Type *dtorTy =
> + llvm::FunctionType::get(CGF.VoidTy, CGF.Int8PtrTy, false)->getPointerTo();
> +
> + // extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d);
> + llvm::Type *paramTys[] = { dtorTy, CGF.Int8PtrTy, CGF.Int8PtrTy };
> + llvm::FunctionType *atexitTy =
> + llvm::FunctionType::get(CGF.IntTy, paramTys, false);
> +
> + // Fetch the actual function.
> + llvm::Constant *atexit =
> + CGF.CGM.CreateRuntimeFunction(atexitTy, "__cxa_atexit");
> + if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit))
> + fn->setDoesNotThrow();
> +
> + // Create a variable that binds the atexit to this shared object.
> + llvm::Constant *handle =
> + CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "__dso_handle");
> +
> + llvm::Value *args[] = {
> + llvm::ConstantExpr::getBitCast(dtor, dtorTy),
> + llvm::ConstantExpr::getBitCast(addr, CGF.Int8PtrTy),
> + handle
> + };
> + CGF.Builder.CreateCall(atexit, args);
> +}
> +
> +static llvm::Function *
> +CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
> + llvm::FunctionType *ty,
> + const Twine &name);
> +
> +/// Create a stub function, suitable for being passed to atexit,
> +/// which passes the given address to the given destructor function.
> +static llvm::Constant *createAtExitStub(CodeGenModule &CGM,
> + llvm::Constant *dtor,
> + llvm::Constant *addr) {
> + // Get the destructor function type, void(*)(void).
> + llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false);
> + llvm::Function *fn =
> + CreateGlobalInitOrDestructFunction(CGM, ty,
> + Twine("__dtor_", addr->getName()));
> +
> + CodeGenFunction CGF(CGM);
> +
> + CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, fn,
> + CGM.getTypes().arrangeNullaryFunction(),
> + FunctionArgList(), SourceLocation());
> +
> + llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
> +
> + // Make sure the call and the callee agree on calling convention.
> + if (llvm::Function *dtorFn =
> + dyn_cast<llvm::Function>(dtor->stripPointerCasts()))
> + call->setCallingConv(dtorFn->getCallingConv());
> +
> + CGF.FinishFunction();
> +
> + return fn;
> +}
> +
> +/// Register a global destructor using atexit.
> +static void emitGlobalDtorWithAtExit(CodeGenFunction &CGF,
> + llvm::Constant *dtor,
> + llvm::Constant *addr) {
> + // Create a function which calls the destructor.
> + llvm::Constant *dtorStub = createAtExitStub(CGF.CGM, dtor, addr);
> +
> + // extern "C" int atexit(void (*f)(void));
> + llvm::FunctionType *atexitTy =
> + llvm::FunctionType::get(CGF.IntTy, dtorStub->getType(), false);
> +
> + llvm::Constant *atexit =
> + CGF.CGM.CreateRuntimeFunction(atexitTy, "atexit");
> + if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit))
> + atexitFn->setDoesNotThrow();
> +
> + CGF.Builder.CreateCall(atexit, dtorStub);
> +}
> +
> +void CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *dtor,
> + llvm::Constant *addr) {
> + // Use __cxa_atexit if available.
> + if (CGM.getCodeGenOpts().CXAAtExit) {
> + emitGlobalDtorWithCXAAtExit(*this, dtor, addr);
> return;
> }
>
> - // Get the destructor function type
> - llvm::Type *DtorFnTy = llvm::FunctionType::get(VoidTy, Int8PtrTy, false);
> - DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
> -
> - llvm::Type *Params[] = { DtorFnTy, Int8PtrTy, Int8PtrTy };
> -
> - // Get the __cxa_atexit function type
> - // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
> - llvm::FunctionType *AtExitFnTy =
> - llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
> -
> - llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
> - "__cxa_atexit");
> - if (llvm::Function *Fn = dyn_cast<llvm::Function>(AtExitFn))
> - Fn->setDoesNotThrow();
> + // In Apple kexts, we want to add a global destructor entry.
> + // FIXME: shouldn't this be guarded by some variable?
> + if (CGM.getContext().getLangOpts().AppleKext) {
> + // Generate a global destructor entry.
> + CGM.AddCXXDtorEntry(dtor, addr);
> + }
>
> - llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
> - "__dso_handle");
> - llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
> - llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
> - llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
> - Builder.CreateCall(AtExitFn, Args);
> + // Otherwise, we just use atexit.
> + emitGlobalDtorWithAtExit(*this, dtor, addr);
> }
>
> void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
>
> Modified: cfe/trunk/test/CodeGenCXX/arm.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=154191&r1=154190&r2=154191&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/arm.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/arm.cpp Fri Apr 6 13:21:06 2012
> @@ -20,9 +20,17 @@
>
> // 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 [[BAR:%.*]]* @_ZN3barC1Ev(
> +// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_baz)
> +
> +// CHECK: define internal void @__dtor_baz()
> +// CHECK: call [[BAR]]* @_ZN3barD1Ev([[BAR]]* @baz)
> +
> // Destructors and constructors must return this.
> namespace test1 {
> void foo();
> @@ -357,5 +365,5 @@
> // 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)
>
> Modified: cfe/trunk/test/CodeGenCXX/global-dtor-no-atexit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/global-dtor-no-atexit.cpp?rev=154191&r1=154190&r2=154191&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/global-dtor-no-atexit.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/global-dtor-no-atexit.cpp Fri Apr 6 13:21:06 2012
> @@ -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([[A:%.*]]* @a)
> +// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_a)
> +// CHECK: define internal void @__dtor_a() nounwind
> +// CHECK: call void @_ZN1AD1Ev([[A]]* @a)
> +
> +// CHECK: call void @_ZN1AC1Ev([[A]]* @b)
> +// CHECK-NEXT: call i32 @atexit(void ()* @__dtor_b)
> +// CHECK: define internal void @__dtor_b() nounwind
> +// CHECK: call void @_ZN1AD1Ev([[A]]* @b)
>
> class A {
> public:
> @@ -15,3 +20,25 @@
> };
>
> A a, b;
> +
> +// PR9593
> +// CHECK: define void @_Z4funcv()
> +// CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZ4funcvE2a1)
> +// CHECK: call void @_ZN1AC1Ev([[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([[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([[A]]* @_ZZ4funcvE2a1)
> +
> +// CHECK: define internal void @__dtor__ZZ4funcvE2a2() nounwind
> +// CHECK: call void @_ZN1AD1Ev([[A]]* @_ZZ4funcvE2a2)
> +
> +void func() {
> + static A a1, a2;
> +}
>
> Modified: cfe/trunk/test/CodeGenCXX/global-init.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/global-init.cpp?rev=154191&r1=154190&r2=154191&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/global-init.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/global-init.cpp Fri Apr 6 13:21:06 2012
> @@ -12,7 +12,7 @@
>
> struct D { ~D(); };
>
> -// CHECK: @__dso_handle = external unnamed_addr global i8*
> +// CHECK: @__dso_handle = external unnamed_addr global i8
> // CHECK: @c = global %struct.C zeroinitializer, align 8
>
> // It's okay if we ever implement the IR-generation optimization to remove this.
> @@ -24,18 +24,18 @@
> // CHECK: @_ZN6PR59741bE = global %"struct.PR5974::B"* bitcast (i8* getelementptr (i8* bitcast (%"struct.PR5974::C"* @_ZN6PR59741cE to i8*), i64 4) to %"struct.PR5974::B"*), align 8
>
> // CHECK: call void @_ZN1AC1Ev(%struct.A* @a)
> -// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
> +// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @a, i32 0, i32 0), i8* @__dso_handle)
> A a;
>
> // CHECK: call void @_ZN1BC1Ev(%struct.B* @b)
> -// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.B*)* @_ZN1BD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.B* @b, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
> +// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.B*)* @_ZN1BD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.B* @b, i32 0, i32 0), i8* @__dso_handle)
> B b;
>
> // PR6205: this should not require a global initializer
> // CHECK-NOT: call void @_ZN1CC1Ev(%struct.C* @c)
> C c;
>
> -// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.D*)* @_ZN1DD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.D* @d, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
> +// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.D*)* @_ZN1DD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.D* @d, i32 0, i32 0), i8* @__dso_handle)
> D d;
>
> // <rdar://problem/7458115>
>
> Modified: cfe/trunk/test/CodeGenCXX/static-init.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-init.cpp?rev=154191&r1=154190&r2=154191&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/static-init.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/static-init.cpp Fri Apr 6 13:21:06 2012
> @@ -17,7 +17,7 @@
> // CHECK: load atomic i8* bitcast (i64* @_ZGVZ1fvE1a to i8*) acquire, align 1
> // CHECK: call i32 @__cxa_guard_acquire
> // CHECK: call void @_ZN1AC1Ev
> - // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @_ZZ1fvE1a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
> + // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @_ZZ1fvE1a, i32 0, i32 0), i8* @__dso_handle)
> // CHECK: call void @__cxa_guard_release
> static A a;
> }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list