From cb006dd715aa5f66d06d42ef78f0b89a15f3e661 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 31 Aug 2025 23:18:27 +0200 Subject: [PATCH] - Compiler module-scope pointer to slice with offset, causes assert. #2446 --- releasenotes.md | 1 + src/compiler/llvm_codegen_expr.c | 20 ++++++++++++++++--- test/test_suite/globals/global_slice.c3t | 25 ++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 test/test_suite/globals/global_slice.c3t diff --git a/releasenotes.md b/releasenotes.md index af4ab6201..2ef2c3b96 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -89,6 +89,7 @@ - Enum inference, like `Foo x = $eval("A")`, now works correctly for `$eval`. - Fix regression where files were added more than once. #2442 - Disambiguate types when they have the same name and need cast between each other. +- Compiler module-scope pointer to slice with offset, causes assert. #2446 ### Stdlib changes - Add `==` to `Pair`, `Triple` and TzDateTime. Add print to `Pair` and `Triple`. diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index ee40c7423..d0e7774f0 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -721,11 +721,19 @@ static inline void llvm_emit_subscript_addr(GenContext *c, BEValue *value, Expr bool start_from_end = expr->subscript_expr.index.start_from_end; if (parent_type_kind == TYPE_SLICE) { - needs_len = safe_mode_enabled() || start_from_end; + needs_len = (safe_mode_enabled() && !llvm_is_global_eval(c)) || start_from_end; if (needs_len) { - llvm_emit_slice_len(c, value, &len); - llvm_value_rvalue(c, &len); + if (LLVMIsAGlobalVariable(value->value)) + { + llvm_value_set(&len, LLVMGetInitializer(value->value), parent_type); + llvm_emit_slice_len(c, &len, &len); + } + else + { + llvm_emit_slice_len(c, value, &len); + llvm_value_rvalue(c, &len); + } } } else if (parent_type_kind == TYPE_ARRAY || parent_type_kind == TYPE_VECTOR) @@ -5080,11 +5088,17 @@ void llvm_emit_slice_pointer(GenContext *c, BEValue *slice, BEValue *pointer) llvm_value_fold_optional(c, slice); if (slice->kind == BE_ADDRESS) { + if (LLVMIsAGlobalVariable(slice->value)) + { + llvm_value_set(slice, LLVMGetInitializer(slice->value), slice->type); + goto NEXT; + } AlignSize alignment; LLVMValueRef ptr = llvm_emit_struct_gep_raw(c, slice->value, llvm_get_type(c, slice->type), 0, slice->alignment, &alignment); llvm_value_set_address(c, pointer, ptr, ptr_type, alignment); return; } +NEXT:; LLVMValueRef ptr = llvm_emit_extract_value(c, slice->value, 0); llvm_value_set(pointer, ptr, ptr_type); } diff --git a/test/test_suite/globals/global_slice.c3t b/test/test_suite/globals/global_slice.c3t new file mode 100644 index 000000000..850539d26 --- /dev/null +++ b/test/test_suite/globals/global_slice.c3t @@ -0,0 +1,25 @@ +module other_module; +int[] list_of_ints = { 1, 2, 3 }; +int* ref_to_2nd = &list_of_ints[^1]; + +module somemain; +import other_module, std; +fn void main() => @pool() +{ + io::printfn("ptr %p", other_module::ref_to_2nd); + *other_module::ref_to_2nd = 42; + io::printfn("%s", other_module::list_of_ints); +} + +/* #expect: other_module.ll + +; ModuleID = 'other_module' +source_filename = "other_module" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" +target triple = "aarch64-apple-macosx11.0.0" + +%"int[]" = type { ptr, i64 } + +@.__const_slice = private unnamed_addr global [3 x i32] [i32 1, i32 2, i32 3], align 4 +@other_module.list_of_ints = local_unnamed_addr global %"int[]" { ptr @.__const_slice, i64 3 }, align 8 +@other_module.ref_to_2nd = local_unnamed_addr global ptr getelementptr inbounds (i8, ptr @.__const_slice, i64 8), align 8