From 9436efe55432799220e105247d0f6a0b7a37ea38 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 20 May 2024 14:42:09 +0200 Subject: [PATCH] Compiler crash on designated initializer for structs with bitstruct. --- releasenotes.md | 1 + src/compiler/llvm_codegen_expr.c | 6 +-- .../bitstruct/bitstruct_direct_in_struct.c3t | 38 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 test/test_suite/bitstruct/bitstruct_direct_in_struct.c3t diff --git a/releasenotes.md b/releasenotes.md index 27eab7527..a07bc66f1 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -21,6 +21,7 @@ - Assertion failed when casting (unsigned) argument to enum #1196 - Correct debug info on parameters without storage. - Fix location on foreach debug output. +- Compiler crash on designated initializer for structs with bitstruct. ### Stdlib changes - Add 'zstr' variants for `string::new_format` / `string::tformat`. diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 85c03dfdb..9946251e2 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -2004,7 +2004,7 @@ static void llvm_emit_initialize_designated_element(GenContext *c, BEValue *ref, { Decl *decl = ref->type->canonical->decl->strukt.members[curr->index]; offset += decl->offset; - Type *type = decl->type->canonical; + Type *type = type_flatten(decl->type); unsigned decl_alignment = decl->alignment; if (ref->type->type_kind == TYPE_UNION) { @@ -2017,11 +2017,11 @@ static void llvm_emit_initialize_designated_element(GenContext *c, BEValue *ref, { llvm_value_struct_gep(c, &value, ref, (unsigned) curr->index); } - if (decl->decl_kind == DECL_BITSTRUCT) + if (type->type_kind == TYPE_BITSTRUCT) { assert(llvm_value_is_addr(&value)); assert(last == current + 1); - Decl *member = decl->bitstruct.members[last[0]->index]; + Decl *member = type->decl->bitstruct.members[last[0]->index]; // Special handling of bitstructs. Type *underlying_type = value.type; assert(!emitted_value); diff --git a/test/test_suite/bitstruct/bitstruct_direct_in_struct.c3t b/test/test_suite/bitstruct/bitstruct_direct_in_struct.c3t new file mode 100644 index 000000000..4d23a5105 --- /dev/null +++ b/test/test_suite/bitstruct/bitstruct_direct_in_struct.c3t @@ -0,0 +1,38 @@ +// #target: macos-x64 +module test; +bitstruct Flags : int { + bool flag1; +} + +struct Foo { + long x; + Flags flags; +} + +fn int main(String[] args) { + long x; + Foo foo = { + .x = x, + .flags.flag1 = true, + }; + return 0; +} + +/* #expect: test.ll + + store ptr %0, ptr %args, align 8 + %ptradd = getelementptr inbounds i8, ptr %args, i64 8 + store i64 %1, ptr %ptradd, align 8 + store i64 0, ptr %x, align 8 + store i64 0, ptr %foo, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %foo, i64 8 + store i32 0, ptr %ptradd1, align 8 + %2 = load i64, ptr %x, align 8 + store i64 %2, ptr %foo, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %foo, i64 8 + %3 = load i32, ptr %ptradd2, align 8 + %4 = and i32 %3, -2 + %5 = or i32 %4, 1 + store i32 %5, ptr %ptradd2, align 8 + ret i32 0 +