Use atexit to fix finalizers on Windows #1361.

This commit is contained in:
Christoffer Lerno
2024-09-14 15:21:00 +02:00
committed by Christoffer Lerno
parent 45a94cfe86
commit 3ab201ce10
7 changed files with 37 additions and 6 deletions

View File

@@ -24,6 +24,7 @@
- Correct '.so' suffix on dynamic libraries on Linux.
- Fix bug where inline index access to array in a struct would crash the compiler.
- Asserts are now correctly included and traced in when running tests.
- Use atexit to fix finalizers on Windows #1361.
### Stdlib changes
- Additional init functions for hashmap.

View File

@@ -2,8 +2,8 @@ import std::io;
fn void main()
{
Path path = path::getcwd()!!;
foreach (i, p : path::ls(path)!!)
Path path = path::new_cwd()!!;
foreach (i, p : path::new_ls(path)!!)
{
io::printfn("%02d %s", i, p.str_view());
}

View File

@@ -2,6 +2,12 @@ module test;
import std::io;
import std::collections::map;
import std::os;
import libc;
fn void bye() @finalizer
{
libc::puts("Bye from finalizer!");
}
fn void test1()
{

View File

@@ -406,10 +406,26 @@ void llvm_emit_function_body(GenContext *c, Decl *decl)
DEBUG_LOG("Generating function %s.", decl->name);
if (decl->func_decl.attr_dynamic) vec_add(c->dynamic_functions, decl);
assert(decl->backend_ref);
if (decl->func_decl.attr_init || decl->func_decl.attr_finalizer)
if (decl->func_decl.attr_init || (decl->func_decl.attr_finalizer && compiler.platform.object_format == OBJ_FORMAT_MACHO))
{
llvm_append_xxlizer(c, decl->func_decl.priority, decl->func_decl.attr_init, decl->backend_ref);
}
if (decl->func_decl.attr_finalizer && compiler.platform.object_format != OBJ_FORMAT_MACHO)
{
LLVMValueRef atexit = LLVMGetNamedFunction(c->module, "atexit");
if (!atexit) atexit = LLVMAddFunction(c->module, "atexit", c->atexit_type);
scratch_buffer_clear();
scratch_buffer_append(".__c3_atexit_");
scratch_buffer_set_extern_decl_name(decl, false);
LLVMValueRef func = LLVMAddFunction(c->module, scratch_buffer_to_string(), c->xtor_func_type);
LLVMBuilderRef builder = llvm_create_function_entry(c, func, NULL);
LLVMValueRef args[1] = { decl->backend_ref };
LLVMBuildCall2(builder, c->atexit_type, atexit, args, 1, "");
LLVMBuildRetVoid(builder);
LLVMDisposeBuilder(builder);
llvm_append_xxlizer(c, decl->func_decl.priority, true, func);
}
llvm_emit_body(c,
decl->backend_ref,
type_get_resolved_prototype(decl->type),

View File

@@ -97,6 +97,7 @@ typedef struct GenContext_
LLVMTypeRef bool_type;
LLVMTypeRef byte_type;
LLVMTypeRef introspect_type;
LLVMTypeRef atexit_type;
LLVMTypeRef fault_type;
LLVMTypeRef size_type;
LLVMTypeRef typeid_type;

View File

@@ -131,13 +131,15 @@ void gencontext_begin_module(GenContext *c)
c->ptr_type = LLVMPointerType(c->byte_type, 0);
c->size_type = llvm_get_type(c, type_usz);
c->typeid_type = llvm_get_type(c, type_typeid);
LLVMTypeRef void_type = LLVMVoidTypeInContext(c->context);
LLVMTypeRef dtable_type[3] = { c->ptr_type, c->ptr_type, c->ptr_type };
c->dtable_type = LLVMStructTypeInContext(c->context, dtable_type, 3, false);
c->chars_type = llvm_get_type(c, type_chars);
LLVMTypeRef ctor_type[3] = { LLVMInt32TypeInContext(c->context), c->ptr_type, c->ptr_type };
c->xtor_entry_type = LLVMStructTypeInContext(c->context, ctor_type, 3, false);
c->xtor_func_type = LLVMFunctionType(LLVMVoidTypeInContext(c->context), NULL, 0, false);
c->xtor_func_type = LLVMFunctionType(void_type, NULL, 0, false);
c->introspect_type = create_introspection_type(c);
c->atexit_type = LLVMFunctionType(void_type, &c->ptr_type, 1, false);
c->fault_type = create_fault_type(c);
c->memcmp_function = NULL;
LLVMTypeRef memcmp_types[3] = {c->ptr_type, c->ptr_type, c->size_type };

View File

@@ -31,8 +31,7 @@ fn void shutdown() @finalizer
/* #expect: test.ll
@llvm.global_ctors = appending global [4 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 300, ptr @test.startup2, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @test.start_main, ptr null }, { i32, ptr, ptr } { i32 200, ptr @test.startup1, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @test.empty_startup, ptr null }]
@llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @test.shutdown, ptr null }]
@llvm.global_ctors = appending global [5 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 300, ptr @test.startup2, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @test.start_main, ptr null }, { i32, ptr, ptr } { i32 200, ptr @test.startup1, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @test.empty_startup, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @.__c3_atexit_test.shutdown, ptr null }]
define void @test.startup2() #0 {
entry:
@@ -60,4 +59,10 @@ define void @test.shutdown() #0 {
entry:
call void @puts(ptr @.str.4)
ret void
}
define void @.__c3_atexit_test.shutdown() {
entry:
call void @atexit(ptr @test.shutdown)
ret void
}