[LLVMdev] runStaticConstructorsDestructors not calling static destructors

Graham Wakefield wakefield at mat.ucsb.edu
Fri Sep 9 13:36:35 PDT 2011


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