Fix ivar in multi-module mode.

This commit is contained in:
Harold Brenes
2025-04-21 02:43:16 -04:00
parent a3de9c8de4
commit b3b4d501ca
2 changed files with 54 additions and 29 deletions
+36 -9
View File
@@ -1588,6 +1588,13 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) {
// Emit method wrapper implementations and registration // Emit method wrapper implementations and registration
auto wrapper_args = array_make<Type *>(temporary_allocator(), 2, 8); auto wrapper_args = array_make<Type *>(temporary_allocator(), 2, 8);
PtrMap<Type *, lbObjCGlobal> ivar_map{};
map_init(&ivar_map, gen->objc_ivars.count);
for (lbObjCGlobal g = {}; mpsc_dequeue(&gen->objc_ivars, &g); /**/) {
map_set(&ivar_map, g.class_impl_type, g);
}
for (const auto& cd : class_impls) { for (const auto& cd : class_impls) {
auto& g = cd.g; auto& g = cd.g;
Type *class_type = g.class_impl_type; Type *class_type = g.class_impl_type;
@@ -1700,7 +1707,9 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) {
// Add ivar if we have one // Add ivar if we have one
Type *ivar_type = class_type->Named.type_name->TypeName.objc_ivar; Type *ivar_type = class_type->Named.type_name->TypeName.objc_ivar;
if (ivar_type != nullptr) { lbObjCGlobal *g_ivar = map_get(&ivar_map, class_type);
if (ivar_type != nullptr && g_ivar != nullptr) {
// Register a single ivar for this class // Register a single ivar for this class
Type *ivar_base = ivar_type->Named.base; Type *ivar_base = ivar_type->Named.base;
// TODO(harold): No idea if I can use this, but I assume so? // TODO(harold): No idea if I can use this, but I assume so?
@@ -1723,10 +1732,33 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) {
args.count = 1; args.count = 1;
args[0] = class_value; args[0] = class_value;
lb_emit_runtime_call(p, "objc_registerClassPair", args); lb_emit_runtime_call(p, "objc_registerClassPair", args);
}
// Register ivars
Type *ptr_u32 = alloc_type_pointer(t_u32);
for (auto const& kv : ivar_map) {
lbObjCGlobal const& g = kv.value;
lbAddr ivar_addr = {};
lbValue *found = string_map_get(&m->members, g.global_name);
if (found) {
ivar_addr = lb_addr(*found);
} else {
// Defined in an external package, must define now
LLVMTypeRef t = lb_type(m, t_u32);
lbValue global{};
global.value = LLVMAddGlobal(m->mod, t, g.global_name);
global.type = ptr_u32;
LLVMSetInitializer(global.value, LLVMConstInt(t, 0, true));
ivar_addr = lb_addr(global);
}
String class_name = g.class_impl_type->Named.type_name->TypeName.objc_class_name;
lbValue class_value = string_map_must_get(&global_class_map, class_name).class_value;
// If we have an ivar, store its offset globally for an intrinsic
// TODO(harold): Only do this for types that had ivar_get calls registered!
if (ivar_type != nullptr) {
args.count = 2; args.count = 2;
args[0] = class_value; args[0] = class_value;
args[1] = lb_const_value(m, t_cstring, exact_value_string(str_lit("__$ivar"))); args[1] = lb_const_value(m, t_cstring, exact_value_string(str_lit("__$ivar")));
@@ -1737,13 +1769,8 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) {
lbValue ivar_offset = lb_emit_runtime_call(p, "ivar_getOffset", args); lbValue ivar_offset = lb_emit_runtime_call(p, "ivar_getOffset", args);
lbValue ivar_offset_u32 = lb_emit_conv(p, ivar_offset, t_u32); lbValue ivar_offset_u32 = lb_emit_conv(p, ivar_offset, t_u32);
String class_name = class_type->Named.type_name->TypeName.objc_class_name;
// TODO(harold): Oops! This is wrong, that map is there to prevent re-entry.
// Simply emit from referred ivars. For now use a single module only.
lbAddr ivar_addr = string_map_must_get(&m->objc_ivars, class_name);
lb_addr_store(p, ivar_addr, ivar_offset_u32); lb_addr_store(p, ivar_addr, ivar_offset_u32);
} }
}
lb_end_procedure_body(p); lb_end_procedure_body(p);
} }
+4 -6
View File
@@ -2165,28 +2165,26 @@ gb_internal lbAddr lb_handle_objc_find_or_register_ivar(lbModule *m, Type *self_
return *found; return *found;
} }
lbModule *default_module = &m->gen->default_module; lbModule *default_module = &m->gen->default_module;
gbString global_name = gb_string_make(permanent_allocator(), "__$objc_ivar::"); gbString global_name = gb_string_make(permanent_allocator(), "__$objc_ivar::");
global_name = gb_string_append_length(global_name, name.text, name.len); global_name = gb_string_append_length(global_name, name.text, name.len);
// Create a global variable to store offset of the ivar in an instance of an object // Create a global variable to store offset of the ivar in an instance of an object
Type *p_ivar_offset = alloc_type_pointer(t_u32); LLVMTypeRef t = lb_type(m, t_u32);
LLVMTypeRef t = lb_type(m, p_ivar_offset);
lbValue g = {}; lbValue g = {};
g.value = LLVMAddGlobal(m->mod, t, global_name); g.value = LLVMAddGlobal(m->mod, t, global_name);
g.type = p_ivar_offset; g.type = alloc_type_pointer(t_u32);
if (default_module == m) { if (default_module == m) {
LLVMSetInitializer(g.value, LLVMConstNull(t)); LLVMSetInitializer(g.value, LLVMConstInt(t, 0, true));
lb_add_member(m, make_string_c(global_name), g); lb_add_member(m, make_string_c(global_name), g);
} else { } else {
LLVMSetLinkage(g.value, LLVMExternalLinkage); LLVMSetLinkage(g.value, LLVMExternalLinkage);
} }
mpsc_enqueue(&m->gen->objc_ivars, lbObjCGlobal{m, global_name, name, self_type}); mpsc_enqueue(&m->gen->objc_ivars, lbObjCGlobal{m, global_name, name, t_u32, self_type});
lbAddr addr = lb_addr(g); lbAddr addr = lb_addr(g);
string_map_set(&m->objc_ivars, name, addr); string_map_set(&m->objc_ivars, name, addr);