From 8785c2c46fe90c2dc9a45fe6dd4a18451a7f345a Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 11 Jan 2025 22:42:33 +0100 Subject: [PATCH] Assert when partially initializing a constant struct containing a slice #1812. --- releasenotes.md | 1 + src/compiler/llvm_codegen.c | 11 +++--- test/test_suite/struct/const_slice_struct.c3t | 37 +++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 test/test_suite/struct/const_slice_struct.c3t diff --git a/releasenotes.md b/releasenotes.md index eef24f4f0..60cc974c1 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -76,6 +76,7 @@ - Fix bug preventing compile time slices from being iterated over with `$foreach`. - Fix bug with defer assignment in macro #1807. - Fix regression with swizzle references for vectors #1810. +- Assert when partially initializing a constant struct containing a slice #1812. ### Stdlib changes - Increase BitWriter.write_bits limit up to 32 bits. diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 3341ebb48..e822ae464 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -233,21 +233,20 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_ switch (const_init->kind) { case CONST_INIT_ZERO: - ASSERT0(const_init->type->type_kind != TYPE_SLICE); return llvm_get_zero(c, const_init->type); case CONST_INIT_ARRAY_VALUE: UNREACHABLE case CONST_INIT_ARRAY_FULL: { - ASSERT0(const_init->type->type_kind != TYPE_SLICE); + ASSERT(const_init, const_init->type->type_kind != TYPE_SLICE); bool was_modified = false; Type *array_type = const_init->type; Type *element_type = array_type->array.base; LLVMTypeRef element_type_llvm = llvm_get_type(c, element_type); ConstInitializer **elements = const_init->init_array_full; - ASSERT0(array_type->type_kind == TYPE_ARRAY || array_type->type_kind == TYPE_VECTOR); + ASSERT(const_init, array_type->type_kind == TYPE_ARRAY || array_type->type_kind == TYPE_VECTOR); ArraySize size = array_type->array.len; - ASSERT0(size > 0); + ASSERT(const_init, size > 0); LLVMValueRef *parts = VECNEW(LLVMValueRef, size); for (ArrayIndex i = 0; i < (ArrayIndex)size; i++) { @@ -268,14 +267,14 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_ case CONST_INIT_ARRAY: { - ASSERT0(const_init->type->type_kind != TYPE_SLICE); + ASSERT(const_init, const_init->type->type_kind != TYPE_SLICE); bool was_modified = false; Type *array_type = const_init->type; Type *element_type = array_type->array.base; LLVMTypeRef element_type_llvm = llvm_get_type(c, element_type); AlignSize expected_align = llvm_abi_alignment(c, element_type_llvm); ConstInitializer **elements = const_init->init_array.elements; - ASSERT0(vec_size(elements) > 0 && "Array should always have gotten at least one element."); + ASSERT(const_init, vec_size(elements) > 0 && "Array should always have gotten at least one element."); ArrayIndex current_index = 0; unsigned alignment = 0; LLVMValueRef *parts = NULL; diff --git a/test/test_suite/struct/const_slice_struct.c3t b/test/test_suite/struct/const_slice_struct.c3t new file mode 100644 index 000000000..837488e2e --- /dev/null +++ b/test/test_suite/struct/const_slice_struct.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module test; +// Issue #1812 +struct Foo +{ + float a; + String b; +} + +struct Bar +{ + float a; + int[] b; +} +const Foo FOO = {.a = 1}; +const Bar FOO2 = {.a = 1, .b = { 1, 3 } }; + +fn int main() +{ + Foo asdf = FOO; + Bar foek = FOO2; + return 0; +} + +/* #expect: test.ll + +@test.FOO = local_unnamed_addr constant %Foo { float 1.000000e+00, %"char[]" zeroinitializer }, align 8 +@.__const_slice = private unnamed_addr global [2 x i32] [i32 1, i32 3], align 4 +@test.FOO2 = local_unnamed_addr constant %Bar { float 1.000000e+00, %"int[]" { ptr @.__const_slice, i64 2 } }, align 8 + +entry: + %asdf = alloca %Foo, align 8 + %foek = alloca %Bar, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %asdf, ptr align 8 @test.FOO, i32 24, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %foek, ptr align 8 @test.FOO2, i32 24, i1 false) + ret i32 0 +}