From bca02f81cd5affa288bac0cc0ed08fe730072aec Mon Sep 17 00:00:00 2001 From: Harold Brenes Date: Tue, 22 Apr 2025 19:16:29 -0400 Subject: Include the ivar in the Objective-C class unconditionally of it being used or not. Allow pseudo-fields for ivar access. --- src/llvm_backend_expr.cpp | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index c5ea0ddac..b9c01ad03 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -5138,8 +5138,6 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { return lb_build_addr(p, unparen_expr(se->selector)); } - - Type *type = base_type(tav.type); if (tav.mode == Addressing_Type) { // Addressing_Type Selection sel = lookup_field(tav.type, selector, true); if (sel.pseudo_field) { @@ -5174,18 +5172,37 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { return lb_addr_swizzle(a, type, swizzle_count, swizzle_indices); } - Selection sel = lookup_field(type, selector, false); + Selection sel = lookup_field(tav.type, selector, false); GB_ASSERT(sel.entity != nullptr); - if (sel.pseudo_field) { - GB_ASSERT(sel.entity->kind == Entity_Procedure || sel.entity->kind == Entity_ProcGroup); + if (sel.pseudo_field && (sel.entity->kind == Entity_Procedure || sel.entity->kind == Entity_ProcGroup)) { + // GB_ASSERT(sel.entity->kind == Entity_Procedure || sel.entity->kind == Entity_ProcGroup); Entity *e = entity_of_node(sel_node); GB_ASSERT(e->kind == Entity_Procedure); return lb_addr(lb_find_value_from_entity(p->module, e)); } - if (sel.is_bit_field) { - lbAddr addr = lb_build_addr(p, se->expr); + lbAddr addr = lb_build_addr(p, se->expr); + + // TODO(harold): Ensure objc_ivar is always null when objc_implement is not set! + Type *d_type = type_deref(tav.type); //base_type(tav.type); + if (d_type->kind == Type_Named && d_type->Named.type_name->TypeName.objc_ivar) { + // NOTE(harold): We need to load the ivar from the current address and + // replace addr with the loaded ivar addr to apply the selector load properly. + + // If it's a deep pointer, dereference it first + // TODO(harold): Ensure this is save to do here. lb_emit_deep_field_gep() has several derefs, once per index. + // Not sure what multiple indices represent... + Type* type = tav.type; + if (is_type_pointer(type)) { + type = type_deref(type); + addr = lb_addr(lb_emit_load(p, addr.addr)); + } + lbValue ivar_ptr = lb_handle_objc_ivar_for_objc_object_pointer(p, addr.addr); + addr = lb_addr(ivar_ptr); + } + + if (sel.is_bit_field) { Selection sub_sel = sel; sub_sel.index.count -= 1; @@ -5211,7 +5228,6 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { } { - lbAddr addr = lb_build_addr(p, se->expr); if (addr.kind == lbAddr_Map) { lbValue v = lb_addr_load(p, addr); lbValue a = lb_address_from_load_or_generate_local(p, v); -- cgit v1.2.3 From 53adff38f08f676bf2e9c40de9040a59c9a8fda6 Mon Sep 17 00:00:00 2001 From: Harold Brenes Date: Tue, 22 Apr 2025 21:44:32 -0400 Subject: Fixes to Ivar pseudo fields. --- src/llvm_backend_expr.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index b9c01ad03..cc49a7be8 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -5192,7 +5192,13 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { // If it's a deep pointer, dereference it first // TODO(harold): Ensure this is save to do here. lb_emit_deep_field_gep() has several derefs, once per index. // Not sure what multiple indices represent... - Type* type = tav.type; + Type* type = type_deref(addr.addr.type); + + // TODO(harold): Checker: Must NOT allow ivar dereferencing on non-pointer types. + // this would access memory outside the size of the value. + // In fact, locals/globals of Objective-C types ought not be allowed at all. + GB_ASSERT(is_type_pointer(type)); + if (is_type_pointer(type)) { type = type_deref(type); addr = lb_addr(lb_emit_load(p, addr.addr)); -- cgit v1.2.3 From c2dfc4b74929354bbbc1395d7dd4568718e3b30c Mon Sep 17 00:00:00 2001 From: Harold Brenes Date: Wed, 30 Apr 2025 20:25:21 -0400 Subject: Cleanup ivar generation for selector expressions. Cleanup ObjC superclass resolution. --- src/check_decl.cpp | 2 +- src/llvm_backend_expr.cpp | 24 +++++------------------- 2 files changed, 6 insertions(+), 20 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index c6746f3eb..a37d20f56 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -575,7 +575,7 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, break; } - super = super->Named.type_name->TypeName.objc_superclass; + super = named_type->Named.type_name->TypeName.objc_superclass; } } else { if (ac.objc_superclass != nullptr) { diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index cc49a7be8..334ce62d5 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -5175,7 +5175,6 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { Selection sel = lookup_field(tav.type, selector, false); GB_ASSERT(sel.entity != nullptr); if (sel.pseudo_field && (sel.entity->kind == Entity_Procedure || sel.entity->kind == Entity_ProcGroup)) { - // GB_ASSERT(sel.entity->kind == Entity_Procedure || sel.entity->kind == Entity_ProcGroup); Entity *e = entity_of_node(sel_node); GB_ASSERT(e->kind == Entity_Procedure); return lb_addr(lb_find_value_from_entity(p->module, e)); @@ -5183,26 +5182,13 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { lbAddr addr = lb_build_addr(p, se->expr); - // TODO(harold): Ensure objc_ivar is always null when objc_implement is not set! - Type *d_type = type_deref(tav.type); //base_type(tav.type); - if (d_type->kind == Type_Named && d_type->Named.type_name->TypeName.objc_ivar) { + // NOTE(harold): Only allow ivar pseudo field access on indirect selectors. + // It is incoherent otherwise as Objective-C objects are zero-sized. + Type *deref_type = type_deref(tav.type); + if (tav.type->kind == Type_Pointer && deref_type->kind == Type_Named && deref_type->Named.type_name->TypeName.objc_ivar) { // NOTE(harold): We need to load the ivar from the current address and // replace addr with the loaded ivar addr to apply the selector load properly. - - // If it's a deep pointer, dereference it first - // TODO(harold): Ensure this is save to do here. lb_emit_deep_field_gep() has several derefs, once per index. - // Not sure what multiple indices represent... - Type* type = type_deref(addr.addr.type); - - // TODO(harold): Checker: Must NOT allow ivar dereferencing on non-pointer types. - // this would access memory outside the size of the value. - // In fact, locals/globals of Objective-C types ought not be allowed at all. - GB_ASSERT(is_type_pointer(type)); - - if (is_type_pointer(type)) { - type = type_deref(type); - addr = lb_addr(lb_emit_load(p, addr.addr)); - } + addr = lb_addr(lb_emit_load(p, addr.addr)); lbValue ivar_ptr = lb_handle_objc_ivar_for_objc_object_pointer(p, addr.addr); addr = lb_addr(ivar_ptr); -- cgit v1.2.3 From ab9593250295137d0a654e942965feee7f506206 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 19 May 2025 20:44:27 +0200 Subject: -dynamic-literals --- src/build_settings.cpp | 1 + src/check_expr.cpp | 2 +- src/llvm_backend_expr.cpp | 2 +- src/main.cpp | 5 +++++ 4 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 04101761c..8364bbfbe 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -459,6 +459,7 @@ struct BuildContext { bool ignore_unknown_attributes; bool no_bounds_check; bool no_type_assert; + bool dynamic_literals; // Opt-in to `#+feature dynamic-literals` project-wide. bool no_output_files; bool no_crt; bool no_rpath; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7ccca1b57..167052772 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -9433,7 +9433,7 @@ gb_internal bool is_expr_inferred_fixed_array(Ast *type_expr) { } gb_internal bool check_for_dynamic_literals(CheckerContext *c, Ast *node, AstCompoundLit *cl) { - if (cl->elems.count > 0 && (check_feature_flags(c, node) & OptInFeatureFlag_DynamicLiterals) == 0) { + if (cl->elems.count > 0 && (check_feature_flags(c, node) & OptInFeatureFlag_DynamicLiterals) == 0 && !build_context.dynamic_literals) { ERROR_BLOCK(); error(node, "Compound literals of dynamic types are disabled by default"); error_line("\tSuggestion: If you want to enable them for this specific file, add '#+feature dynamic-literals' at the top of the file\n"); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 0909b189a..e17d958d7 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4844,7 +4844,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { if (cl->elems.count == 0) { break; } - GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals); + GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals || build_context.dynamic_literals); lbValue err = lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos); gb_unused(err); diff --git a/src/main.cpp b/src/main.cpp index 00032c1ff..3692e4f06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -319,6 +319,7 @@ enum BuildFlagKind { BuildFlag_NoBoundsCheck, BuildFlag_NoTypeAssert, BuildFlag_NoDynamicLiterals, + BuildFlag_DynamicLiterals, BuildFlag_NoCRT, BuildFlag_NoRPath, BuildFlag_NoEntryPoint, @@ -538,6 +539,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_NoTypeAssert, str_lit("no-type-assert"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoThreadLocal, str_lit("no-thread-local"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoDynamicLiterals, str_lit("no-dynamic-literals"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_DynamicLiterals, str_lit("dynamic-literals"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoRPath, str_lit("no-rpath"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoEntryPoint, str_lit("no-entry-point"), BuildFlagParam_None, Command__does_check &~ Command_test); @@ -1207,6 +1209,9 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_NoDynamicLiterals: gb_printf_err("Warning: Use of -no-dynamic-literals is now redundant\n"); break; + case BuildFlag_DynamicLiterals: + build_context.dynamic_literals = true; + break; case BuildFlag_NoCRT: build_context.no_crt = true; break; -- cgit v1.2.3