diff --git a/releasenotes.md b/releasenotes.md index 4c21a76e7..fe76295d1 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -38,6 +38,7 @@ - Compile time indexing at compile time in a $typeof was no considered compile time. - Slicing a constant array with designated initialization would not update the indexes. - Fix for bug when `@format` encountered `*` in some cases. +- Compiler segfault on global slice initialization with null[:0] #2404. ### 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 da2498b68..ab45bdb48 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -2638,19 +2638,26 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r ASSERT(slice->expr_kind == EXPR_SLICE); Expr *parent_expr = exprptr(slice->subscript_expr.expr); - Type *parent_type = type_flatten(parent_expr->type); + parent_type = type_no_optional(parent_type); BEValue parent_addr_x; llvm_emit_expr(c, &parent_addr_x, parent_expr); - llvm_value_addr(c, &parent_addr_x); - LLVMValueRef parent_addr = parent_addr_x.value; LLVMValueRef parent_load_value = NULL; LLVMValueRef parent_base; - parent_type = type_no_optional(parent_type); + LLVMValueRef parent_addr; + if (parent_type->type_kind == TYPE_POINTER) + { + llvm_value_rvalue(c, &parent_addr_x); + parent_load_value = parent_base = parent_addr_x.value; + } + else + { + llvm_value_addr(c, &parent_addr_x); + parent_addr = parent_addr_x.value; + } switch (parent_type->type_kind) { case TYPE_POINTER: - parent_load_value = parent_base = LLVMBuildLoad2(c->builder, llvm_get_type(c, parent_type), parent_addr, ""); break; case TYPE_SLICE: parent_load_value = LLVMBuildLoad2(c->builder, llvm_get_type(c, parent_type), parent_addr, ""); diff --git a/test/test_suite/arrays/slice_null_const.c3t b/test/test_suite/arrays/slice_null_const.c3t new file mode 100644 index 000000000..50793154a --- /dev/null +++ b/test/test_suite/arrays/slice_null_const.c3t @@ -0,0 +1,19 @@ +// #target: macos-x64 +module test; +char[] bad @export = null[:0]; + +fn void main() +{ + char[] good = null[:0]; +} + +/* #expect: test.ll + +@test__bad = local_unnamed_addr global %"char[]" zeroinitializer, align 8 + +define void @test.main() #0 { +entry: + %good = alloca %"char[]", align 8 + store %"char[]" zeroinitializer, ptr %good, align 8 + ret void +} diff --git a/test/test_suite/debug_symbols/defer_macro.c3t b/test/test_suite/debug_symbols/defer_macro.c3t index 479344f64..b2f559a01 100644 --- a/test/test_suite/debug_symbols/defer_macro.c3t +++ b/test/test_suite/debug_symbols/defer_macro.c3t @@ -373,7 +373,6 @@ entry: %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 %retparam = alloca ptr, align 8 - %taddr = alloca ptr, align 8 %varargslots = alloca [1 x %any], align 16 %indirectarg = alloca %"any[]", align 8 %i = alloca i32, align 4 @@ -467,79 +466,75 @@ after_check: ; preds = %match expr_block.exit: ; preds = %after_check, %if.then %25 = load ptr, ptr %blockret11, align 8, !dbg !167 - store ptr %25, ptr %taddr, align 8 - %26 = load ptr, ptr %taddr, align 8 - %27 = load i64, ptr %elements8, align 8, !dbg !168 - %add = add i64 0, %27, !dbg !168 + %26 = load i64, ptr %elements8, align 8, !dbg !168 + %add = add i64 0, %26, !dbg !168 %size13 = sub i64 %add, 0, !dbg !168 - %28 = insertvalue %"char[][]" undef, ptr %26, 0, !dbg !168 - %29 = insertvalue %"char[][]" %28, i64 %size13, 1, !dbg !168 + %27 = insertvalue %"char[][]" undef, ptr %25, 0, !dbg !168 + %28 = insertvalue %"char[][]" %27, i64 %size13, 1, !dbg !168 br label %noerr_block, !dbg !168 panic_block: ; preds = %assign_optional - %30 = insertvalue %any undef, ptr %error_var, 0, !dbg !168 - %31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.fault" to i64), 1, !dbg !168 - store %any %31, ptr %varargslots, align 16 - %32 = insertvalue %"any[]" undef, ptr %varargslots, 0 - %"$$temp" = insertvalue %"any[]" %32, i64 1, 1 + %29 = insertvalue %any undef, ptr %error_var, 0, !dbg !168 + %30 = insertvalue %any %29, i64 ptrtoint (ptr @"$ct.fault" to i64), 1, !dbg !168 + store %any %30, ptr %varargslots, align 16 + %31 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %31, i64 1, 1 store %"any[]" %"$$temp", ptr %indirectarg, align 8 - call void @std.core.builtin.panicf(ptr @.panic_msg.1 + call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 36, ptr @.file, i64 16, ptr @.func, i64 6, i32 287, ptr byval(%"any[]") align 8 %indirectarg) #5, !dbg !157 unreachable, !dbg !157 noerr_block: ; preds = %expr_block.exit - store %"char[][]" %29, ptr %list5, align 8, !dbg !157 - + store %"char[][]" %28, ptr %list5, align 8, !dbg !157 store i32 0, ptr %i, align 4, !dbg !172 br label %loop.cond, !dbg !172 loop.cond: ; preds = %loop.exit, %noerr_block - %33 = load i32, ptr %i, align 4, !dbg !173 - %34 = load i32, ptr %argc2, align 4, !dbg !174 - %lt = icmp slt i32 %33, %34, !dbg !173 + %32 = load i32, ptr %i, align 4, !dbg !173 + %33 = load i32, ptr %argc2, align 4, !dbg !174 + %lt = icmp slt i32 %32, %33, !dbg !173 br i1 %lt, label %loop.body, label %loop.exit26, !dbg !173 loop.body: ; preds = %loop.cond - %35 = load ptr, ptr %argv3, align 8, !dbg !178 - %36 = load i32, ptr %i, align 4, !dbg !179 - %sext14 = sext i32 %36 to i64, !dbg !179 - %ptroffset = getelementptr inbounds [8 x i8], ptr %35, i64 %sext14, !dbg !179 - %37 = load ptr, ptr %ptroffset, align 8, !dbg !179 - store ptr %37, ptr %arg, align 8, !dbg !179 - + %34 = load ptr, ptr %argv3, align 8, !dbg !178 + %35 = load i32, ptr %i, align 4, !dbg !179 + %sext14 = sext i32 %35 to i64, !dbg !179 + %ptroffset = getelementptr inbounds [8 x i8], ptr %34, i64 %sext14, !dbg !179 + %36 = load ptr, ptr %ptroffset, align 8, !dbg !179 + store ptr %36, ptr %arg, align 8, !dbg !179 store i64 0, ptr %len, align 8, !dbg !182 - %38 = load ptr, ptr %arg, align 8, !dbg !183 - %39 = load ptr, ptr %arg, align 8 - store ptr %39, ptr %ptr, align 8 + %37 = load ptr, ptr %arg, align 8, !dbg !183 + %38 = load ptr, ptr %arg, align 8 + store ptr %38, ptr %ptr, align 8 store i64 0, ptr %len16, align 8, !dbg !188 br label %loop.cond17, !dbg !189 loop.cond17: ; preds = %loop.body19, %loop.body - %40 = load ptr, ptr %ptr, align 8, !dbg !190 - %41 = load i64, ptr %len16, align 8, !dbg !192 - %ptradd18 = getelementptr inbounds i8, ptr %40, i64 %41, !dbg !192 - %42 = load i8, ptr %ptradd18, align 1, !dbg !192 - %i2b = icmp ne i8 %42, 0, !dbg !192 + %39 = load ptr, ptr %ptr, align 8, !dbg !190 + %40 = load i64, ptr %len16, align 8, !dbg !192 + %ptradd18 = getelementptr inbounds i8, ptr %39, i64 %40, !dbg !192 + %41 = load i8, ptr %ptradd18, align 1, !dbg !192 + %i2b = icmp ne i8 %41, 0, !dbg !192 br i1 %i2b, label %loop.body19, label %loop.exit, !dbg !192 loop.body19: ; preds = %loop.cond17 - %43 = load i64, ptr %len16, align 8, !dbg !193 - %add20 = add i64 %43, 1, !dbg !193 + %42 = load i64, ptr %len16, align 8, !dbg !193 + %add20 = add i64 %42, 1, !dbg !193 store i64 %add20, ptr %len16, align 8, !dbg !193 br label %loop.cond17, !dbg !193 loop.exit: ; preds = %loop.cond17 - %44 = load i64, ptr %len16, align 8, !dbg !194 - %add21 = add i64 0, %44, !dbg !194 + %43 = load i64, ptr %len16, align 8, !dbg !194 + %add21 = add i64 0, %43, !dbg !194 %size22 = sub i64 %add21, 0, !dbg !194 - %45 = insertvalue %"char[]" undef, ptr %38, 0, !dbg !194 - %46 = insertvalue %"char[]" %45, i64 %size22, 1, !dbg !194 - %47 = load ptr, ptr %list5, align 8, !dbg !195 - %48 = load i32, ptr %i, align 4, !dbg !196 - %sext23 = sext i32 %48 to i64, !dbg !196 - %ptroffset24 = getelementptr inbounds [16 x i8], ptr %47, i64 %sext23, !dbg !196 - store %"char[]" %46, ptr %ptroffset24, align 8, !dbg !196 - %49 = load i32, ptr %i, align 4, !dbg !197 - %add25 = add i32 %49, 1, !dbg !197 + %44 = insertvalue %"char[]" undef, ptr %37, 0, !dbg !194 + %45 = insertvalue %"char[]" %44, i64 %size22, 1, !dbg !194 + %46 = load ptr, ptr %list5, align 8, !dbg !195 + %47 = load i32, ptr %i, align 4, !dbg !196 + %sext23 = sext i32 %47 to i64, !dbg !196 + %ptroffset24 = getelementptr inbounds [16 x i8], ptr %46, i64 %sext23, !dbg !196 + store %"char[]" %45, ptr %ptroffset24, align 8, !dbg !196 + %48 = load i32, ptr %i, align 4, !dbg !197 + %add25 = add i32 %48, 1, !dbg !197 store i32 %add25, ptr %i, align 4, !dbg !197 br label %loop.cond, !dbg !197 @@ -548,15 +543,15 @@ loop.exit26: ; preds = %loop.cond %lo = load ptr, ptr %list, align 8, !dbg !199 %ptradd27 = getelementptr inbounds i8, ptr %list, i64 8, !dbg !199 %hi = load i64, ptr %ptradd27, align 8, !dbg !199 - %50 = call i32 @test.main(ptr %lo, i64 %hi), !dbg !200 - store i32 %50, ptr %blockret, align 4, !dbg !200 - %51 = load ptr, ptr %list, align 8, !dbg !201 - call void @std.core.mem.free(ptr %51) #4, !dbg !203 + %49 = call i32 @test.main(ptr %lo, i64 %hi), !dbg !200 + store i32 %49, ptr %blockret, align 4, !dbg !200 + %50 = load ptr, ptr %list, align 8, !dbg !201 + call void @std.core.mem.free(ptr %50) #4, !dbg !203 br label %expr_block.exit28, !dbg !203 expr_block.exit28: ; preds = %loop.exit26 - %52 = load i32, ptr %blockret, align 4, !dbg !203 - ret i32 %52, !dbg !203 + %51 = load i32, ptr %blockret, align 4, !dbg !203 + ret i32 %51, !dbg !203 } declare { i32, ptr } @attach.to_scope() #0 diff --git a/test/test_suite/defer/defer_catch_mix.c3t b/test/test_suite/defer/defer_catch_mix.c3t index f4230bc19..ae2b9d42e 100644 --- a/test/test_suite/defer/defer_catch_mix.c3t +++ b/test/test_suite/defer/defer_catch_mix.c3t @@ -295,14 +295,13 @@ entry: %taddr4 = alloca %"char[]", align 8 %taddr5 = alloca %"char[]", align 8 %retparam = alloca ptr, align 8 - %taddr6 = alloca ptr, align 8 + %taddr6 = alloca %"char[]", align 8 %taddr7 = alloca %"char[]", align 8 %taddr8 = alloca %"char[]", align 8 - %taddr9 = alloca %"char[]", align 8 %varargslots = alloca [1 x %any], align 8 - %taddr10 = alloca %"any[]", align 8 - %retparam14 = alloca %"char[]", align 8 - %taddr15 = alloca %"char[]", align 8 + %taddr9 = alloca %"any[]", align 8 + %retparam13 = alloca %"char[]", align 8 + %taddr14 = alloca %"char[]", align 8 store ptr null, ptr %.cachedtype, align 8 %0 = call ptr @llvm.threadlocal.address.p0(ptr @std.core.mem.allocator.thread_allocator) call void @llvm.memcpy.p0.p0.i32(ptr align 8 %allocator, ptr align 8 %0, i32 16, i1 false) @@ -343,7 +342,7 @@ missing_function: ; preds = %6 store %"char[]" { ptr @.func, i64 4 }, ptr %taddr5, align 8 %10 = load [2 x i64], ptr %taddr5, align 8 %11 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %11([2 x i64] %8, [2 x i64] %9, [2 x i64] %10, + call void %11([2 x i64] %8, [2 x i64] %9, [2 x i64] %10, i32 98) #4 unreachable match: ; preds = %6 @@ -359,60 +358,58 @@ assign_optional: ; preds = %match after_check: ; preds = %match %15 = load ptr, ptr %retparam, align 8 - store ptr %15, ptr %taddr6, align 8 - %16 = load ptr, ptr %taddr6, align 8 - %17 = insertvalue %"char[]" undef, ptr %16, 0 - %18 = insertvalue %"char[]" %17, i64 12, 1 + %16 = insertvalue %"char[]" undef, ptr %15, 0 + %17 = insertvalue %"char[]" %16, i64 12, 1 br label %noerr_block panic_block: ; preds = %assign_optional - %19 = insertvalue %any undef, ptr %error_var, 0 - %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 - store %"char[]" { ptr @.panic_msg.4, i64 36 }, ptr %taddr7, align 8 + %18 = insertvalue %any undef, ptr %error_var, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 + store %"char[]" { ptr @.panic_msg.4, i64 36 }, ptr %taddr6, align 8 + %20 = load [2 x i64], ptr %taddr6, align 8 + store %"char[]" { ptr @.file, i64 16 }, ptr %taddr7, align 8 %21 = load [2 x i64], ptr %taddr7, align 8 - store %"char[]" { ptr @.file, i64 16 }, ptr %taddr8, align 8 + store %"char[]" { ptr @.func, i64 4 }, ptr %taddr8, align 8 %22 = load [2 x i64], ptr %taddr8, align 8 - store %"char[]" { ptr @.func, i64 4 }, ptr %taddr9, align 8 - %23 = load [2 x i64], ptr %taddr9, align 8 - store %any %20, ptr %varargslots, align 8 - %24 = insertvalue %"any[]" undef, ptr %varargslots, 0 - %"$$temp" = insertvalue %"any[]" %24, i64 1, 1 - store %"any[]" %"$$temp", ptr %taddr10, align 8 - %25 = load [2 x i64], ptr %taddr10, align 8 - call void @std.core.builtin.panicf([2 x i64] %21, [2 x i64] %22, [2 x i64] %23, + store %any %19, ptr %varargslots, align 8 + %23 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %23, i64 1, 1 + store %"any[]" %"$$temp", ptr %taddr9, align 8 + %24 = load [2 x i64], ptr %taddr9, align 8 + call void @std.core.builtin.panicf([2 x i64] %20, [2 x i64] %21, [2 x i64] %22, i32 262, [2 x i64] %24) #4 unreachable noerr_block: ; preds = %after_check - store %"char[]" %18, ptr %buffer, align 8 + store %"char[]" %17, ptr %buffer, align 8 store i64 0, ptr %buffer.f, align 8 %optval = load i64, ptr %buffer.f, align 8 - %not_err11 = icmp eq i64 %optval, 0 - %26 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) - br i1 %26, label %after_check13, label %assign_optional12 + %not_err10 = icmp eq i64 %optval, 0 + %25 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %25, label %after_check12, label %assign_optional11 -assign_optional12: ; preds = %noerr_block +assign_optional11: ; preds = %noerr_block store i64 %optval, ptr %buffer.f, align 8 br label %after_assign -after_check13: ; preds = %noerr_block - store %"char[]" { ptr @.str.5, i64 13 }, ptr %taddr15, align 8 - %27 = load [2 x i64], ptr %taddr15, align 8 - %28 = load [2 x i64], ptr %buffer, align 8 - %29 = call i64 @test.fileReader(ptr %retparam14, [2 x i64] %27, [2 x i64] %28) - %not_err16 = icmp eq i64 %29, 0 - %30 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) - br i1 %30, label %after_check18, label %assign_optional17 +after_check12: ; preds = %noerr_block + store %"char[]" { ptr @.str.5, i64 13 }, ptr %taddr14, align 8 + %26 = load [2 x i64], ptr %taddr14, align 8 + %27 = load [2 x i64], ptr %buffer, align 8 + %28 = call i64 @test.fileReader(ptr %retparam13, [2 x i64] %26, [2 x i64] %27) + %not_err15 = icmp eq i64 %28, 0 + %29 = call i1 @llvm.expect.i1(i1 %not_err15, i1 true) + br i1 %29, label %after_check17, label %assign_optional16 -assign_optional17: ; preds = %after_check13 - store i64 %29, ptr %buffer.f, align 8 +assign_optional16: ; preds = %after_check12 + store i64 %28, ptr %buffer.f, align 8 br label %after_assign -after_check18: ; preds = %after_check13 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %buffer, ptr align 8 %retparam14, i32 16, i1 false) +after_check17: ; preds = %after_check12 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %buffer, ptr align 8 %retparam13, i32 16, i1 false) store i64 0, ptr %buffer.f, align 8 br label %after_assign -after_assign: ; preds = %after_check18, %assign_optional17, %assign_optional12 +after_assign: ; preds = %after_check17, %assign_optional16, %assign_optional11 ret void }