[LLVMdev] runStaticConstructorsDestructors not calling static destructors

Graham Wakefield wakefield at mat.ucsb.edu
Fri Sep 9 13:41:44 PDT 2011


Another data point - it looks like the destructors are called when the running program exits (which crashes because the machine code has been freed).

Is there a configuration to LLVM or Clang to tell it to put the destructors in a different location than __cxa_atexit ?

Thanks~

On Sep 9, 2011, at 1:36 PM, Graham Wakefield wrote:

> Hi there,
> 
> I'm having trouble getting ExecutionEngine->runStaticConstructorsDestructors(module, true) to actually trigger static destructors in my code. The static constructors however do get called. 
> 
> I don't know if this is an LLVM or Clang issue, from looking at the IR (see below) it looks like the destructor is being tied to cxa_atexit, and I wonder if that is not called by runStaticConstructorsDestructors(module, true);
> 
> Thanks in advance for any suggestions you can offer!
> 
> Graham
> 
> 
> Using LLVM/Clang 2.9 release for OSX, on OSX 10.6.8, on a core i7 macbook pro.
> 
> I'm compiling from C++ using Clang, and passing the compiled module to an ExecutionEngine created as follows:
> 
> EE = llvm::EngineBuilder(globalModule)
> 			.setEngineKind(llvm::EngineKind::JIT)
> 			.setErrorStr(&err)
> 			.setOptLevel(llvm::CodeGenOpt::Default)
> 			.setAllocateGVsWithCode(false)
> 			//.setMAttrs("-avx")
> 			.setMCPU("core2")
> 			.create();
> EE->DisableLazyCompilation();
> 
> After passing in the compiled module, I call:
> 
> EE->runStaticConstructorsDestructors(module, false);
> 
> Then to test the tear-down of the module, I call:
> 
> EE->runStaticConstructorsDestructors(mImpl->module, true);
> EE->clearGlobalMappingsFromModule(mImpl->module);
> EE->removeModule(mImpl->module);	
> 
> 
> 
> The C++ code compiled:
> 
> #include <stdio.h>
> class Foo {
> public:
> 	Foo() { printf("Foo\n"); };
> 	~Foo() { printf("~Foo\n"); };
> 
> 	int x;
> };
> 
> // a static variable:
> Foo foo;	
> 
> 
> The constructor is being called (I see 'Foo' in my stdout), but the destructor is not.
> 
> 
> The LLVM IR produced:
> 
> ; ModuleID = 'mymodule'
> target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
> target triple = "i386-apple-darwin10"
> 
> %0 = type { i32, void ()* }
> %class.Foo = type { i32 }
> 
> @foo = global %class.Foo zeroinitializer, align 4
> @__dso_handle = external global i8*
> @.str = private unnamed_addr constant [6 x i8] c"~Foo\0A\00"
> @.str1 = private unnamed_addr constant [5 x i8] c"Foo\0A\00"
> @llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I_a }]
> 
> define internal void @__cxx_global_var_init() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" {
> call void @_ZN3FooC1Ev(%class.Foo* @foo)
> %1 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%class.Foo*)* @_ZN3FooD1Ev to void (i8*)*), i8* bitcast (%class.Foo* @foo to i8*), i8* bitcast (i8** @__dso_handle to i8*))
> ret void
> }
> 
> define linkonce_odr void @_ZN3FooC1Ev(%class.Foo* %this) unnamed_addr nounwind align 2 {
> %1 = alloca %class.Foo*, align 4
> store %class.Foo* %this, %class.Foo** %1, align 4
> %2 = load %class.Foo** %1
> call void @_ZN3FooC2Ev(%class.Foo* %2)
> ret void
> }
> 
> define linkonce_odr void @_ZN3FooD1Ev(%class.Foo* %this) unnamed_addr nounwind align 2 {
> %1 = alloca %class.Foo*, align 4
> store %class.Foo* %this, %class.Foo** %1, align 4
> %2 = load %class.Foo** %1
> call void @_ZN3FooD2Ev(%class.Foo* %2)
> ret void
> }
> 
> declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
> 
> define linkonce_odr void @_ZN3FooD2Ev(%class.Foo* %this) unnamed_addr nounwind align 2 {
> %1 = alloca %class.Foo*, align 4
> store %class.Foo* %this, %class.Foo** %1, align 4
> %2 = load %class.Foo** %1
> %3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0))
> ret void
> }
> 
> declare i32 @printf(i8*, ...)
> 
> define linkonce_odr void @_ZN3FooC2Ev(%class.Foo* %this) unnamed_addr nounwind align 2 {
> %1 = alloca %class.Foo*, align 4
> store %class.Foo* %this, %class.Foo** %1, align 4
> %2 = load %class.Foo** %1
> %3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str1, i32 0, i32 0))
> ret void
> }
> 
> define internal void @_GLOBAL__I_a() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" {
> call void @__cxx_global_var_init()
> ret void
> }
> 
> 
> 
> I added a JITEventListener, which displays:
> 
> JIT emitted Function _GLOBAL__I_a at 0x1c00010, size 12
> JIT emitted Function __cxx_global_var_init at 0x1c00020, size 47
> JIT emitted Function _ZN3FooD1Ev at 0x1c00060, size 23
> JIT emitted Function _ZN3FooD2Ev at 0x1c00080, size 27
> JIT emitted Function _ZN3FooC1Ev at 0x1c000a0, size 23
> JIT emitted Function _ZN3FooC2Ev at 0x1c000c0, size 27
> 
> JIT freed 0x1c00020
> JIT freed 0x1c000a0
> JIT freed 0x1c00060
> JIT freed 0x1c00080
> JIT freed 0x1c000c0
> JIT freed 0x1c00010
> 





More information about the llvm-dev mailing list