diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index cee8543a7..6363f531f 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -4034,7 +4034,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte Decl *member = members[i]; if (member->decl_kind != DECL_VAR && !member->name) { - int sub_element_count = decl_count_elements(members[i]); + int sub_element_count = decl_count_elements(member); if (!sub_element_count) { vec_add(initializer->initializer_list, NULL); @@ -4093,9 +4093,28 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte if (expr_is_constant_eval(initializer, CONSTANT_EVAL_ANY)) { + bool is_union = type_flatten_distinct(initializer->type)->type_kind == TYPE_UNION; + assert(!is_union || vec_size(elements) == 1); ConstInitializer *const_init = CALLOCS(ConstInitializer); - const_init->kind = CONST_INIT_STRUCT; + const_init->kind = is_union ? CONST_INIT_UNION : CONST_INIT_STRUCT; const_init->type = type_flatten(initializer->type); + if (is_union) + { + Expr *expr = elements[0]; + const_init->init_union.index = 0; + if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST) + { + const_init->init_union.element = expr->const_expr.list; + } + else + { + ConstInitializer *element_init = MALLOCS(ConstInitializer); + sema_create_const_initializer_value(element_init, expr); + const_init->init_union.element = element_init; + } + expr_set_as_const_list(initializer, const_init); + return true; + } ConstInitializer **inits = MALLOC(sizeof(ConstInitializer *) * vec_size(elements)); VECEACH(elements, i) { diff --git a/src/version.h b/src/version.h index 5d8065056..9bd0e304f 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.2.11" \ No newline at end of file +#define COMPILER_VERSION "0.2.12" \ No newline at end of file diff --git a/test/test_suite/struct/nested_struct_union_init.c3t b/test/test_suite/struct/nested_struct_union_init.c3t new file mode 100644 index 000000000..67ffafa58 --- /dev/null +++ b/test/test_suite/struct/nested_struct_union_init.c3t @@ -0,0 +1,116 @@ +// #target: macos-x64 +module foob; +import libc; +struct Matrix2x2 +{ + union + { + float[4] m; + struct { + float m00, m01, m10, m11; + } + } +} + +struct Matrix2x2_b +{ + union + { + struct { + float m00, m01, m10, m11; + } + float[4] m; + } +} +struct Matrix4x4 { + union { + struct { + float m00, m01, m02, m03; + float m10, m11, m12, m13; + float m20, m21, m22, m23; + float m30, m31, m32, m33; + } + float[16] m; + } +} + + +struct Matrix3x3 { + union { + struct { + float m00, m01, m02, m10, m11, m12, m20, m21, m22; + } + float[9] m; + } +} +fn void main() +{ + Matrix3x3 x = { 1, 2, 3, 4, 5, 6, 7,8 ,9}; + Matrix2x2 m = { float[4] { 1, 2, 3, 4 } }; + Matrix2x2_b m2 = { 1, 2, 3, 4 }; + libc::printf("%f %f %f %f\n", x.m00, x.m[1], x.m10, x.m[3]); +} + +/* #expect: foob.ll + +%Matrix2x2 = type { %anon.1 } +%anon.1 = type { [4 x float] } +%Matrix2x2_b = type { %anon.2 } +%anon.2 = type { %anon.3 } +%anon.3 = type { float, float, float, float } +%Matrix3x3 = type { %anon } +%anon = type { %anon.0 } +%anon.0 = type { float, float, float, float, float, float, float, float, float } + +define void @foob.main() #0 { +entry: + %x = alloca %Matrix3x3, align 4 + %m = alloca %Matrix2x2, align 4 + %m2 = alloca %Matrix2x2_b, align 4 + %0 = getelementptr inbounds %Matrix3x3, %Matrix3x3* %x, i32 0, i32 0 + %1 = bitcast %anon* %0 to %anon.0* + %2 = getelementptr inbounds %anon.0, %anon.0* %1, i32 0, i32 0 + store float 1.000000e+00, float* %2, align 4 + %3 = getelementptr inbounds %anon.0, %anon.0* %1, i32 0, i32 1 + store float 2.000000e+00, float* %3, align 4 + %4 = getelementptr inbounds %anon.0, %anon.0* %1, i32 0, i32 2 + store float 3.000000e+00, float* %4, align 4 + %5 = getelementptr inbounds %anon.0, %anon.0* %1, i32 0, i32 3 + store float 4.000000e+00, float* %5, align 4 + %6 = getelementptr inbounds %anon.0, %anon.0* %1, i32 0, i32 4 + store float 5.000000e+00, float* %6, align 4 + %7 = getelementptr inbounds %anon.0, %anon.0* %1, i32 0, i32 5 + store float 6.000000e+00, float* %7, align 4 + %8 = getelementptr inbounds %anon.0, %anon.0* %1, i32 0, i32 6 + store float 7.000000e+00, float* %8, align 4 + %9 = getelementptr inbounds %anon.0, %anon.0* %1, i32 0, i32 7 + store float 8.000000e+00, float* %9, align 4 + %10 = getelementptr inbounds %anon.0, %anon.0* %1, i32 0, i32 8 + store float 9.000000e+00, float* %10, align 4 + %11 = bitcast %Matrix2x2* %m to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %11, i8* align 4 bitcast (%Matrix2x2* @.__const to i8*), i32 16, i1 false) + %12 = bitcast %Matrix2x2_b* %m2 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %12, i8* align 4 bitcast (%Matrix2x2_b* @.__const.8 to i8*), i32 16, i1 false) + %13 = getelementptr inbounds %Matrix3x3, %Matrix3x3* %x, i32 0, i32 0 + %14 = bitcast %anon* %13 to %anon.0* + %15 = getelementptr inbounds %anon.0, %anon.0* %14, i32 0, i32 0 + %16 = load float, float* %15, align 4 + %fpfpext = fpext float %16 to double + %17 = getelementptr inbounds %Matrix3x3, %Matrix3x3* %x, i32 0, i32 0 + %18 = bitcast %anon* %17 to [9 x float]* + %19 = getelementptr inbounds [9 x float], [9 x float]* %18, i64 0, i64 1 + %20 = load float, float* %19, align 4 + %fpfpext1 = fpext float %20 to double + %21 = getelementptr inbounds %Matrix3x3, %Matrix3x3* %x, i32 0, i32 0 + %22 = bitcast %anon* %21 to %anon.0* + %23 = getelementptr inbounds %anon.0, %anon.0* %22, i32 0, i32 3 + %24 = load float, float* %23, align 4 + %fpfpext2 = fpext float %24 to double + %25 = getelementptr inbounds %Matrix3x3, %Matrix3x3* %x, i32 0, i32 0 + %26 = bitcast %anon* %25 to [9 x float]* + %27 = getelementptr inbounds [9 x float], [9 x float]* %26, i64 0, i64 3 + %28 = load float, float* %27, align 4 + %fpfpext3 = fpext float %28 to double + %29 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i32 0, i32 0), double %fpfpext, double %fpfpext1, double %fpfpext2, double %fpfpext3) + ret void +} diff --git a/test/test_suite2/struct/nested_struct_union_init.c3t b/test/test_suite2/struct/nested_struct_union_init.c3t new file mode 100644 index 000000000..22637eb52 --- /dev/null +++ b/test/test_suite2/struct/nested_struct_union_init.c3t @@ -0,0 +1,110 @@ +// #target: macos-x64 +module foob; +import libc; +struct Matrix2x2 +{ + union + { + float[4] m; + struct { + float m00, m01, m10, m11; + } + } +} + +struct Matrix2x2_b +{ + union + { + struct { + float m00, m01, m10, m11; + } + float[4] m; + } +} +struct Matrix4x4 { + union { + struct { + float m00, m01, m02, m03; + float m10, m11, m12, m13; + float m20, m21, m22, m23; + float m30, m31, m32, m33; + } + float[16] m; + } +} + + +struct Matrix3x3 { + union { + struct { + float m00, m01, m02, m10, m11, m12, m20, m21, m22; + } + float[9] m; + } +} +fn void main() +{ + Matrix3x3 x = { 1, 2, 3, 4, 5, 6, 7,8 ,9}; + Matrix2x2 m = { float[4] { 1, 2, 3, 4 } }; + Matrix2x2_b m2 = { 1, 2, 3, 4 }; + libc::printf("%f %f %f %f\n", x.m00, x.m[1], x.m10, x.m[3]); +} + +/* #expect: foob.ll + +%Matrix2x2 = type { %anon.1 } +%anon.1 = type { [4 x float] } +%Matrix2x2_b = type { %anon.2 } +%anon.2 = type { %anon.3 } +%anon.3 = type { float, float, float, float } +%Matrix3x3 = type { %anon } +%anon = type { %anon.0 } +%anon.0 = type { float, float, float, float, float, float, float, float, float } + + +define void @foob.main() #0 { +entry: + %x = alloca %Matrix3x3, align 4 + %m = alloca %Matrix2x2, align 4 + %m2 = alloca %Matrix2x2_b, align 4 + %0 = getelementptr inbounds %Matrix3x3, ptr %x, i32 0, i32 0 + %1 = getelementptr inbounds %anon.0, ptr %0, i32 0, i32 0 + store float 1.000000e+00, ptr %1, align 4 + %2 = getelementptr inbounds %anon.0, ptr %0, i32 0, i32 1 + store float 2.000000e+00, ptr %2, align 4 + %3 = getelementptr inbounds %anon.0, ptr %0, i32 0, i32 2 + store float 3.000000e+00, ptr %3, align 4 + %4 = getelementptr inbounds %anon.0, ptr %0, i32 0, i32 3 + store float 4.000000e+00, ptr %4, align 4 + %5 = getelementptr inbounds %anon.0, ptr %0, i32 0, i32 4 + store float 5.000000e+00, ptr %5, align 4 + %6 = getelementptr inbounds %anon.0, ptr %0, i32 0, i32 5 + store float 6.000000e+00, ptr %6, align 4 + %7 = getelementptr inbounds %anon.0, ptr %0, i32 0, i32 6 + store float 7.000000e+00, ptr %7, align 4 + %8 = getelementptr inbounds %anon.0, ptr %0, i32 0, i32 7 + store float 8.000000e+00, ptr %8, align 4 + %9 = getelementptr inbounds %anon.0, ptr %0, i32 0, i32 8 + store float 9.000000e+00, ptr %9, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m, ptr align 4 @.__const, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m2, ptr align 4 @.__const.8, i32 16, i1 false) + %10 = getelementptr inbounds %Matrix3x3, ptr %x, i32 0, i32 0 + %11 = getelementptr inbounds %anon.0, ptr %10, i32 0, i32 0 + %12 = load float, ptr %11, align 4 + %fpfpext = fpext float %12 to double + %13 = getelementptr inbounds %Matrix3x3, ptr %x, i32 0, i32 0 + %14 = getelementptr inbounds [9 x float], ptr %13, i64 0, i64 1 + %15 = load float, ptr %14, align 4 + %fpfpext1 = fpext float %15 to double + %16 = getelementptr inbounds %Matrix3x3, ptr %x, i32 0, i32 0 + %17 = getelementptr inbounds %anon.0, ptr %16, i32 0, i32 3 + %18 = load float, ptr %17, align 4 + %fpfpext2 = fpext float %18 to double + %19 = getelementptr inbounds %Matrix3x3, ptr %x, i32 0, i32 0 + %20 = getelementptr inbounds [9 x float], ptr %19, i64 0, i64 3 + %21 = load float, ptr %20, align 4 + %fpfpext3 = fpext float %21 to double + %22 = call i32 (ptr, ...) @printf(ptr @.str, double %fpfpext, double %fpfpext1, double %fpfpext2, double %fpfpext3) + ret void +}