mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Prevent Mach-O from removing @init and @dynamic in a more reliable way #1200.
This commit is contained in:
@@ -6,11 +6,11 @@
|
||||
|
||||
### Fixes
|
||||
- Error with unsigned compare in `@ensure` when early returning 0 #1207.
|
||||
- Prevent Mach-O from removing `@init` and `@dynamic` in a more reliable way #1200.
|
||||
|
||||
### Stdlib changes
|
||||
- Added `remove_first_item` `remove_last_item` and `remove_item` as aliases for the `match` functions.
|
||||
|
||||
|
||||
## 0.6.0 Change list
|
||||
|
||||
### Changes / improvements
|
||||
|
||||
@@ -135,10 +135,27 @@ LLVMValueRef llvm_get_selector(GenContext *c, const char *name)
|
||||
}
|
||||
|
||||
|
||||
void llvm_emit_macho_xtor(GenContext *c, LLVMValueRef *list, const char *name)
|
||||
static LLVMValueRef llvm_emit_macho_xtor_use(GenContext *c, LLVMValueRef global, const char *name)
|
||||
{
|
||||
LLVMValueRef initializer = LLVMAddFunction(c->module, name, c->xtor_func_type);
|
||||
LLVMSetLinkage(initializer, LLVMInternalLinkage);
|
||||
LLVMSetAlignment(initializer, 8);
|
||||
LLVMValueRef vals_fn[3] = { llvm_const_int(c, type_int, 1), initializer, llvm_get_zero(c, type_voidptr) };
|
||||
LLVMValueRef result = LLVMConstNamedStruct(c->xtor_entry_type, vals_fn, 3);
|
||||
|
||||
LLVMBasicBlockRef last_block;
|
||||
LLVMBuilderRef builder = llvm_create_function_entry(c, initializer, &last_block);
|
||||
LLVMValueRef load = LLVMBuildLoad2(builder, LLVMTypeOf(LLVMGetInitializer(global)), global, ".retain_global");
|
||||
LLVMSetVolatile(load, true);
|
||||
LLVMBuildRetVoid(builder);
|
||||
LLVMDisposeBuilder(builder);
|
||||
return result;
|
||||
}
|
||||
|
||||
static LLVMValueRef llvm_emit_macho_xtor(GenContext *c, LLVMValueRef *list, const char *name, const char *retain_name)
|
||||
{
|
||||
unsigned len = vec_size(list);
|
||||
if (!len) return;
|
||||
if (!len) return NULL;
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_append(".list$");
|
||||
scratch_buffer_append(name);
|
||||
@@ -151,31 +168,46 @@ void llvm_emit_macho_xtor(GenContext *c, LLVMValueRef *list, const char *name)
|
||||
LLVMSetInitializer(global, array);
|
||||
LLVMSetSection(global, scratch_buffer_to_string());
|
||||
LLVMSetAlignment(global, llvm_abi_alignment(c, c->xtor_entry_type));
|
||||
|
||||
return llvm_emit_macho_xtor_use(c, global, retain_name);
|
||||
}
|
||||
|
||||
void llvm_emit_constructors_and_destructors(GenContext *c)
|
||||
{
|
||||
if (platform_target.object_format == OBJ_FORMAT_MACHO)
|
||||
{
|
||||
llvm_emit_macho_xtor(c, c->constructors, "c3ctor");
|
||||
llvm_emit_macho_xtor(c, c->destructors, "c3dtor");
|
||||
|
||||
LLVMValueRef c3_dynamic = LLVMGetNamedGlobal(c->module, "$c3_dynamic");
|
||||
LLVMValueRef dtor_global = llvm_emit_macho_xtor(c, c->constructors, "c3ctor", ".c3_ctor_retain");
|
||||
LLVMValueRef ctor_global = llvm_emit_macho_xtor(c, c->destructors, "c3dtor", ".c3_dtor_retain");
|
||||
|
||||
LLVMValueRef runtime_start = LLVMGetNamedFunction(c->module, "__c3_runtime_startup");
|
||||
if (!runtime_start || !LLVMGetFirstBasicBlock(runtime_start)) return;
|
||||
LLVMValueRef vals[3] = { llvm_const_int(c, type_int, 65535), runtime_start, llvm_get_zero(c, type_voidptr) };
|
||||
LLVMValueRef entry = LLVMConstNamedStruct(c->xtor_entry_type, vals, 3);
|
||||
LLVMValueRef array = LLVMConstArray(c->xtor_entry_type, &entry, 1);
|
||||
LLVMValueRef global_ctor = LLVMAddGlobal(c->module, LLVMTypeOf(array), "llvm.global_ctors");
|
||||
LLVMSetLinkage(global_ctor, LLVMAppendingLinkage);
|
||||
LLVMSetInitializer(global_ctor, array);
|
||||
int len = 0;
|
||||
LLVMValueRef ctors[5];
|
||||
if (ctor_global) ctors[len++] = ctor_global;
|
||||
if (dtor_global) ctors[len++] = dtor_global;
|
||||
if (c3_dynamic) ctors[len++] = llvm_emit_macho_xtor_use(c, c3_dynamic, ".c3_dynamic_retain");
|
||||
if (!runtime_start || !LLVMGetFirstBasicBlock(runtime_start))
|
||||
{
|
||||
goto EMIT_CTORS;
|
||||
}
|
||||
LLVMValueRef runtime_end = LLVMGetNamedFunction(c->module, "__c3_runtime_finalize");
|
||||
if (!runtime_end || !LLVMGetFirstBasicBlock(runtime_end)) error_exit("Failed to find __c3_runtime_finalize in the same module as __c3_runtime_startup.");
|
||||
vals[1] = runtime_end;
|
||||
entry = LLVMConstNamedStruct(c->xtor_entry_type, vals, 3);
|
||||
array = LLVMConstArray(c->xtor_entry_type, &entry, 1);
|
||||
LLVMValueRef vals[3] = { llvm_const_int(c, type_int, 65535), runtime_end, llvm_get_zero(c, type_voidptr) };
|
||||
LLVMValueRef entry = LLVMConstNamedStruct(c->xtor_entry_type, vals, 3);
|
||||
LLVMValueRef array = LLVMConstArray(c->xtor_entry_type, &entry, 1);
|
||||
LLVMValueRef global_dtor = LLVMAddGlobal(c->module, LLVMTypeOf(array), "llvm.global_dtors");
|
||||
LLVMSetLinkage(global_dtor, LLVMAppendingLinkage);
|
||||
LLVMSetInitializer(global_dtor, array);
|
||||
vals[1] = runtime_start;
|
||||
entry = LLVMConstNamedStruct(c->xtor_entry_type, vals, 3);
|
||||
ctors[len++] = entry;
|
||||
EMIT_CTORS:
|
||||
if (len == 0) return;
|
||||
array = LLVMConstArray(c->xtor_entry_type, ctors, len);
|
||||
LLVMValueRef global_ctor = LLVMAddGlobal(c->module, LLVMTypeOf(array), "llvm.global_ctors");
|
||||
LLVMSetLinkage(global_ctor, LLVMAppendingLinkage);
|
||||
LLVMSetInitializer(global_ctor, array);
|
||||
return;
|
||||
}
|
||||
llvm_emit_xtor(c, c->constructors, "llvm.global_ctors");
|
||||
|
||||
@@ -562,11 +562,6 @@ void llvm_emit_dynamic_functions(GenContext *c, Decl **funcs)
|
||||
LLVMSetInitializer(global, array);
|
||||
LLVMSetSection(global, "__DATA,__c3_dynamic");
|
||||
LLVMSetAlignment(global, llvm_abi_alignment(c, c->xtor_entry_type));
|
||||
LLVMValueRef array_used = LLVMConstArray(LLVMTypeOf(global), &global, 1);
|
||||
LLVMValueRef global_used = LLVMAddGlobal(c->module, LLVMTypeOf(array_used), "llvm.used");
|
||||
LLVMSetLinkage(global_used, LLVMAppendingLinkage);
|
||||
LLVMSetInitializer(global_used, array_used);
|
||||
LLVMSetSection(global_used, "llvm.metadata");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ fn void! delete_contains_index()
|
||||
assert(test.contains(3));
|
||||
test[0] = 10;
|
||||
assert(test.contains(10));
|
||||
test.remove_all_matches(10);
|
||||
test.remove_item(10);
|
||||
assert(test.array_view() == int[]{ 2, 3 });
|
||||
assert(!test.contains(1));
|
||||
assert(test.contains(2));
|
||||
@@ -42,7 +42,7 @@ fn void! delete_contains_index()
|
||||
assert(test.array_view() == int[]{ 0, 2, 3, 0 });
|
||||
assert(test.index_of(0)! == 0);
|
||||
assert(test.rindex_of(0)! == 3);
|
||||
test.remove_all_matches(0);
|
||||
test.remove_item(0);
|
||||
assert(test.len() == 2);
|
||||
assert(test.array_view() == int[]{ 2, 3 });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user