From 5af13f5d53b4e5f5d472cd8a8bc4444f05ea36d6 Mon Sep 17 00:00:00 2001 From: Harold Brenes Date: Tue, 16 Sep 2025 00:49:31 -0400 Subject: Automatically emit objc_msgSend calls when calling imported or implemented Objective-C methods - Add intrinsics.objc_super() - Emit objc_msgSendSuper2 calls when an objc method call is combined with objc_super(self) - Fix objc_block return value ABI for large struct returns - Fix objc_implement method wrappers bad ABI for large struct returns and indirect args - Simplify parameter forwarding for objc_imlpement methods - Add intrinsics.objc_instancetype to mimi Objective-C instancetype* returns This facilitates returning the correct type on subclasses when calling mehtods such as `alloc`, `init`, `retain`, etc. - Refactor Objective-C class implementations generation so that hierarchies are properly initialized - Better codegen for context passing with ivar-based autocontext - Allow @superclass on imported objc-c objects - Better codegen for block forwarding invoker, arguments are forwarded directly --- src/checker.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 32bda2e43..d3c111de4 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1416,6 +1416,8 @@ gb_internal void init_universal(void) { t_objc_SEL = alloc_type_pointer(t_objc_selector); t_objc_Class = alloc_type_pointer(t_objc_class); t_objc_Ivar = alloc_type_pointer(t_objc_ivar); + + t_objc_instancetype = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_instancetype"), t_objc_id); } } @@ -3386,12 +3388,18 @@ gb_internal void init_core_map_type(Checker *c) { t_raw_map_ptr = alloc_type_pointer(t_raw_map); } +gb_internal void init_core_objc_c(Checker *c) { + t_objc_super = find_core_type(c, str_lit("objc_super")); + t_objc_super_ptr = alloc_type_pointer(t_objc_super); +} + gb_internal void init_preload(Checker *c) { init_core_type_info(c); init_mem_allocator(c); init_core_context(c); init_core_source_code_location(c); init_core_map_type(c); + init_core_objc_c(c); } gb_internal ExactValue check_decl_attribute_value(CheckerContext *c, Ast *value) { -- cgit v1.2.3 From fc44b104315ddac114ae756f5d3f1ed236636782 Mon Sep 17 00:00:00 2001 From: Harold Brenes Date: Mon, 29 Sep 2025 20:20:54 -0400 Subject: Include objc runtime type dependencies only on darwin --- src/checker.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index d3c111de4..0a8590570 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3389,8 +3389,10 @@ gb_internal void init_core_map_type(Checker *c) { } gb_internal void init_core_objc_c(Checker *c) { - t_objc_super = find_core_type(c, str_lit("objc_super")); - t_objc_super_ptr = alloc_type_pointer(t_objc_super); + if (build_context.metrics.os == TargetOs_darwin) { + t_objc_super = find_core_type(c, str_lit("objc_super")); + t_objc_super_ptr = alloc_type_pointer(t_objc_super); + } } gb_internal void init_preload(Checker *c) { -- cgit v1.2.3 From 86f9c920dafc40c6bb1eb5cc5461b20ca954459c Mon Sep 17 00:00:00 2001 From: Harold Brenes Date: Sun, 5 Oct 2025 15:50:01 -0400 Subject: Fix Objective-C block symbols naming conflict across modules. Fix assert triggered when there's checker errors and Objective-C method implementations. --- src/checker.cpp | 5 ++++- src/llvm_backend.hpp | 2 +- src/llvm_backend_utility.cpp | 21 +++++++++++---------- 3 files changed, 16 insertions(+), 12 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 0a8590570..2a82203ef 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1501,9 +1501,12 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { map_destroy(&i->objc_msgSend_types); string_set_destroy(&i->obcj_class_name_set); - mpsc_destroy(&i->objc_class_implementations); map_destroy(&i->objc_method_implementations); + // NOTE(harold): Disabling this: It can cause the 'count == 0' assert to trigger + // when there's checker errors and the queue is still full as it did not reach the generation stage. + // mpsc_destroy(&i->objc_class_implementations); + string_map_destroy(&i->load_file_cache); string_map_destroy(&i->load_directory_cache); map_destroy(&i->load_directory_map); diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 6870f6259..6a4616694 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -206,7 +206,7 @@ struct lbModule { StringMap objc_classes; StringMap objc_selectors; StringMap objc_ivars; - isize objc_next_block_id; // Used to name objective-c blocks, per module + std::atomic objc_next_block_id; // Used to name objective-c blocks. IMPORTANT: Tracked on the main module PtrMap map_cell_info_map; // address of runtime.Map_Info PtrMap map_info_map; // address of runtime.Map_Cell_Info diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index ca7bf34e3..60dcf0992 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2271,12 +2271,12 @@ gb_internal lbValue lb_handle_objc_ivar_get(lbProcedure *p, Ast *expr) { } gb_internal void lb_create_objc_block_helper_procs( - lbModule *m, LLVMTypeRef block_lit_type, isize capture_field_offset, + lbModule *m, LLVMTypeRef block_lit_type, isize capture_field_offset, isize block_id, Slice capture_values, Slice objc_object_indices, lbProcedure *&out_copy_helper, lbProcedure *&out_dispose_helper ) { - gbString copy_helper_name = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$objc_block_copy_helper_%lld", m->objc_next_block_id); - gbString dispose_helper_name = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$objc_block_dispose_helper_%lld", m->objc_next_block_id); + gbString copy_helper_name = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$objc_block_copy_helper_%lld", block_id); + gbString dispose_helper_name = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$objc_block_dispose_helper_%lld", block_id); // copy: Block_Literal *dst, Block_Literal *src, i32 field_apropos // dispose: Block_Literal *src, i32 field_apropos @@ -2385,7 +2385,8 @@ gb_internal lbValue lb_handle_objc_block(lbProcedure *p, Ast *expr) { lbModule *m = p->module; - m->objc_next_block_id += 1; + lbModule *default_module = &m->gen->default_module; + const isize block_id = default_module->objc_next_block_id++; const isize capture_arg_count = ce->args.count - 1; @@ -2431,7 +2432,7 @@ gb_internal lbValue lb_handle_objc_block(lbProcedure *p, Ast *expr) { // Create proc with the block signature // (takes a block literal pointer as the first parameter, followed by any expected ones from the user's proc) - gbString block_invoker_name = gb_string_append_fmt(gb_string_make(permanent_allocator(), ""), "__$objc_block_invoker_%lld", m->objc_next_block_id); + gbString block_invoker_name = gb_string_append_fmt(gb_string_make(permanent_allocator(), ""), "__$objc_block_invoker_%lld", block_id); // Add + 1 because the first parameter received is the block literal pointer itself auto invoker_args = array_make(temporary_allocator(), block_forward_args + 1, block_forward_args + 1); @@ -2464,10 +2465,10 @@ gb_internal lbValue lb_handle_objc_block(lbProcedure *p, Ast *expr) { // Create the block descriptor and block literal gbString block_lit_type_name = gb_string_make(temporary_allocator(), "__$ObjC_Block_Literal_"); - block_lit_type_name = gb_string_append_fmt(block_lit_type_name, "%lld", m->objc_next_block_id); + block_lit_type_name = gb_string_append_fmt(block_lit_type_name, "%lld", block_id); gbString block_desc_type_name = gb_string_make(temporary_allocator(), "__$ObjC_Block_Descriptor_"); - block_desc_type_name = gb_string_append_fmt(block_desc_type_name, "%lld", m->objc_next_block_id); + block_desc_type_name = gb_string_append_fmt(block_desc_type_name, "%lld", block_id); LLVMTypeRef block_lit_type = {}; LLVMTypeRef block_desc_type = {}; @@ -2511,7 +2512,7 @@ gb_internal lbValue lb_handle_objc_block(lbProcedure *p, Ast *expr) { // Generate copy and dispose helper functions for captured params that are Objective-C objects (or a Block) if (has_objc_fields) { - lb_create_objc_block_helper_procs(m, block_lit_type, capture_fields_offset, + lb_create_objc_block_helper_procs(m, block_lit_type, capture_fields_offset, block_id, slice(captured_values, 0, captured_values.count), slice(objc_captures, 0, objc_captures.count), copy_helper, dispose_helper); @@ -2530,7 +2531,7 @@ gb_internal lbValue lb_handle_objc_block(lbProcedure *p, Ast *expr) { // Create global block descriptor gbString desc_global_name = gb_string_make(temporary_allocator(), "__$objc_block_desc_"); - desc_global_name = gb_string_append_fmt(desc_global_name, "%lld", m->objc_next_block_id); + desc_global_name = gb_string_append_fmt(desc_global_name, "%lld", block_id); LLVMValueRef p_descriptor = LLVMAddGlobal(m->mod, block_desc_type, desc_global_name); LLVMSetInitializer(p_descriptor, block_desc_initializer); @@ -2614,7 +2615,7 @@ gb_internal lbValue lb_handle_objc_block(lbProcedure *p, Ast *expr) { } gbString block_var_name = gb_string_make(temporary_allocator(), "__$objc_block_literal_"); - block_var_name = gb_string_append_fmt(block_var_name, "%lld", m->objc_next_block_id); + block_var_name = gb_string_append_fmt(block_var_name, "%lld", block_id); lbValue block_result = {}; block_result.type = block_result_type; -- cgit v1.2.3 From e4db455458cc4b376f9983fc9968f6e82fc5ba17 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 11 Oct 2025 20:32:09 +0200 Subject: Fix #5785 --- src/checker.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 2a82203ef..8b3638c9d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -5093,26 +5093,22 @@ gb_internal void add_import_dependency_node(Checker *c, Ast *decl, PtrMapscope != nullptr); - - id->package = pkg; + AstPackage *child_pkg = *found; + GB_ASSERT(child_pkg->scope != nullptr); - ImportGraphNode **found_node = nullptr; - ImportGraphNode *m = nullptr; - ImportGraphNode *n = nullptr; + id->package = child_pkg; - found_node = map_get(M, pkg); + ImportGraphNode **found_node = map_get(M, child_pkg); GB_ASSERT(found_node != nullptr); - m = *found_node; + ImportGraphNode *child = *found_node; found_node = map_get(M, parent_pkg); GB_ASSERT(found_node != nullptr); - n = *found_node; + ImportGraphNode *parent = *found_node; - import_graph_node_set_add(&n->succ, m); - import_graph_node_set_add(&m->pred, n); - ptr_set_add(&m->scope->imported, n->scope); + import_graph_node_set_add(&parent->succ, child); + import_graph_node_set_add(&child->pred, parent); + ptr_set_add(&parent->scope->imported, child->scope); case_end; case_ast_node(ws, WhenStmt, decl); -- cgit v1.2.3