diff options
| author | Harold Brenes <harold@hbrenes.com> | 2025-04-21 02:42:02 -0400 |
|---|---|---|
| committer | Harold Brenes <harold@hbrenes.com> | 2025-04-21 02:43:16 -0400 |
| commit | b3b4d501ca6c1af70c0ceef7610f6c5d83a2d296 (patch) | |
| tree | fe2ebd3228f1b2e867eb659f438b4df261363373 /src | |
| parent | a3de9c8de4e539905a85f3cc060f95529b402f18 (diff) | |
Fix ivar in multi-module mode.
Diffstat (limited to 'src')
| -rw-r--r-- | src/llvm_backend.cpp | 69 | ||||
| -rw-r--r-- | src/llvm_backend_utility.cpp | 14 |
2 files changed, 54 insertions, 29 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 23ad81847..ef975b8c1 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1588,6 +1588,13 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { // Emit method wrapper implementations and registration 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) { auto& g = cd.g; 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 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 Type *ivar_base = ivar_type->Named.base; // TODO(harold): No idea if I can use this, but I assume so? @@ -1723,28 +1732,46 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { args.count = 1; args[0] = class_value; lb_emit_runtime_call(p, "objc_registerClassPair", args); - - // 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[0] = class_value; - args[1] = lb_const_value(m, t_cstring, exact_value_string(str_lit("__$ivar"))); - lbValue ivar = lb_emit_runtime_call(p, "class_getInstanceVariable", args); - - args.count = 1; - args[0] = ivar; - lbValue ivar_offset = lb_emit_runtime_call(p, "ivar_getOffset", args); - 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); - } } + // 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; + + args.count = 2; + args[0] = class_value; + args[1] = lb_const_value(m, t_cstring, exact_value_string(str_lit("__$ivar"))); + lbValue ivar = lb_emit_runtime_call(p, "class_getInstanceVariable", args); + + args.count = 1; + args[0] = ivar; + lbValue ivar_offset = lb_emit_runtime_call(p, "ivar_getOffset", args); + lbValue ivar_offset_u32 = lb_emit_conv(p, ivar_offset, t_u32); + + lb_addr_store(p, ivar_addr, ivar_offset_u32); + } + lb_end_procedure_body(p); } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 897b71b5b..ae7842ce6 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2165,28 +2165,26 @@ gb_internal lbAddr lb_handle_objc_find_or_register_ivar(lbModule *m, Type *self_ return *found; } - lbModule *default_module = &m->gen->default_module; gbString global_name = gb_string_make(permanent_allocator(), "__$objc_ivar::"); 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 - 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 = {}; g.value = LLVMAddGlobal(m->mod, t, global_name); - g.type = p_ivar_offset; + g.type = alloc_type_pointer(t_u32); 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); } else { 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); string_map_set(&m->objc_ivars, name, addr); @@ -2206,8 +2204,8 @@ gb_internal lbValue lb_handle_objc_ivar_get(lbProcedure *p, Ast *expr) { lbValue ivar_offset = lb_addr_load(p, lb_handle_objc_find_or_register_ivar(m, self_type)); lbValue ivar_offset_uptr = lb_emit_conv(p, ivar_offset, t_uintptr); - lbValue self = lb_build_expr(p, ce->args[0]); - lbValue self_uptr = lb_emit_conv(p, self, t_uintptr); + lbValue self = lb_build_expr(p, ce->args[0]); + lbValue self_uptr = lb_emit_conv(p, self, t_uintptr); lbValue ivar_uptr = lb_emit_arith(p, Token_Add, self_uptr, ivar_offset_uptr, t_uintptr); |